fix(approvals): handle JSON recursion limits - #4773
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
There is an earlier I reproduced this by adding a deeply nested payload to
|
linhongyu510
left a comment
There was a problem hiding this comment.
Verified the exact head 06c55c78 against the real decoder failure and the shared approval paths.
On base 89c02c82, an object payload nested to 4 * sys.getrecursionlimit() raises RecursionError: maximum recursion depth exceeded while decoding a JSON object from a unicode string. On this head, the same payload returns None, which keeps both callers fail-closed: the normal runner and Realtime paths interpret an uninspectable callable-policy argument as requiring approval.
I also checked the surrounding parser matrix: a valid object still returns its dict, while malformed JSON, NaN, a top-level list, None, and blank input all return None. Focused validation in the frozen environment:
pytest -q tests/test_approval_utils.py tests/test_run_context_approvals.py tests/realtime/test_session.py -k approval
51 passed, 179 deselected
Ruff check, Ruff format, and git diff --check pass for the two changed files. No functional blocker found.
Non-blocking test improvement: consider adding the issue's real deeply nested JSON payload (derived from sys.getrecursionlimit()) alongside or instead of monkeypatching json.loads. The current mock proves the catch branch, while the real payload also locks the concrete stdlib decoder behavior that made this reachable. At review time this SHA has no remote check runs, so the results above are local evidence rather than a claim that upstream CI is green.
Summary
This pull request keeps function-tool approval argument parsing on its documented best-effort path when Python's JSON decoder hits its recursion limit.
parse_function_tool_arguments()returns parsed object arguments orNonewhen an approval policy cannot inspect them. It already treats malformed JSON and non-standard constants that way by catchingValueError, but sufficiently deeply nested model-supplied JSON causesjson.loads()to raiseRecursionErrorinstead. That exception currently escapes approval handling in both the normal runner and Realtime paths.The fix catches
RecursionErroralongsideValueError. Valid JSON behaviour and the existing object-only return contract are unchanged.Test plan
RecursionErrorand verifiesparse_function_tool_arguments()returnsNone.Issue number
Closes #4772
Checks
.agents/skills/code-change-verification/scripts/run.sh/reviewbefore submitting this PR