#942 with_rate_limit executes a failing tool TWICE (tool exception caught by limiter fail-open branch)

closed critical engine Created 2026-10-16 00:19 · Updated 2026-10-16 00:23

Description

Edit
EARS SPEC: - When a rate-limited tool raises an exception after the rate-limit check passed, the decorator shall propagate that exception and shall have invoked the tool exactly once. - If the rate-limit check itself fails unexpectedly, then the decorator shall invoke the tool at most once. FOUND 2026-10-16 in worker logs during #939 verification: 'Rate limiter error for tools.shell.command: Command docker version returned non-zero exit status 127 (allowing request)' followed by a second 'Executing shell command: docker version'. Cause: engine/tools/decorators/rate_limit.py wrapper calls 'return func(*args, **kwargs)' INSIDE the try; the generic 'except Exception' fail-open branch then calls func again. Affected: tools.http.request, tools.email.send, tools.shell.run, tools.llm.call (every failure = duplicate side effect, e.g. duplicate POST/email). Also seen earlier for tools.llm.call. SYNTHESIS (bugfix, single line): domain = decorator control flow; concept = separate guard evaluation from guarded call (check in try, call outside). Fail-open semantics of the check itself are out of scope here (#928 moves to TokenGate fail-closed).

Comments

Loading comments...

Context

Loading context...

Audit History

View All
Loading audit history...