Skip to content

Native findings review terminates on read_file tool call with empty argument JSON #326

Closed

Description

@acoliver

Actual final independent workload: session followup-transcript-sol-20261003ao, unchanged named astramedium with explicitlocaloauth, accepted317hostingbinarySHA256689f6f954935235a17324dda3efec22e5c1cb8ee1efca7a36a3d421dedcaa9da. Terminal exit5: tool call read_file: invalid argument JSON: EOF while parsing a value at line 1 column 0.

Raw envelope/status retained at branch-2/evalwork/results/pr-remediation-20261002/followup-transcript-attempt-ao.*; candidate64fabimmutable and no approval established. This proves observed empty tool argument failure, not whether provider generation, framing or dispatch produced the empty string. No silent argument repair, tool success fallback, request replay or parser skip added. Explicit same-session continuation preserves existing evidence/child gates and sends proper task instructions, without a new review cycle.

Need identify provenance of empty argument after actual model stream, preserving no automatic ambiguous-request replay. Do not relax strict JSON parsing to hide this symptom or infer third-party cause from envelope alone.

Activity

  1. acoliver commented on Oct 4, 2026

    @acoliver
    ContributorAuthor

    A proven current raw-argument aggregation defect shipped in #330 at main 638ae7b4: received raw {} bytes could be mistaken for a typed initial placeholder and erased by the next fragment. Registered compiled baseline witnesses failed and the byte-preserving fix passed, without permissive JSON repair or request replay.

    This does not establish the cause of the original historical empty read_file arguments. Its retained terminal envelope contains no wire-framing provenance, and that accepted attempt was not replayed. The issue remains open for that uncertainty. Independent review also reproduced a separate pre-existing item/index and done-argument contradiction defect, tracked as #331. Exact-source platform/release/extracted CI and native authenticated edit/test acceptance passed for the narrow byte-preservation delivery.

  2. acoliver commented on Oct 9, 2026

    @acoliver
    ContributorAuthor

    Another occurrence, this time as a Luthor-launched worker for #331 (task task-4f783e5af26185c586db392ae23c3aa2, attempt attempt-d5273f7bc017d38b6501b814ed27f6a6).

    Worker: release build of b526a7f7 (most likely; its .d file points at a checkout whose HEAD was b526a7f7 with a clean tree when the binary was built on Sep 28), sha256 90d3a792054883cc2282d8246ea61c3d89079bfcc74179c5ba95d27931c43dff. Profile: provider codex, model gpt-6.1-sol, reasoning effort high, base URL https://chatgpt.com/backend-api/codex. Flags: --allow-shell --max-tool-calls 512 --turn-time 4h.

    Exit 5 about 60 seconds after launch. Stdout, verbatim:

    {"error":{"code":"invalid-tool-call","message":"tool call read_file: invalid argument JSON: EOF while parsing a value at line 1 column 0"},"session_id":"task-4f783e5af26185c586db392ae23c3aa2","status":"error"}

    Stderr held only the keychain loading notice. The session log shows five admitted calls before the failure: three run_shell_command calls (git status, gh api .../issues/331 written to .issue-331-inspection.txt) and two read_file calls on that file with normal object arguments. The second read_file result was a CTXDIGEST handle whose re-fetch hint names read_file. The next model reply carried a read_file call with an empty argument string, and the branch was recorded as branch_failed with the message above. This again shows only the folded value, not what the wire carried.

    Source trace on main 638ae7b4, which has the same behaviour on this path:

    • vendor/serdes-ai-responses/src/client/assembler.rs:114-121 starts every function-call part with ToolCallArgs::String(String::new()) and ignores item.arguments. Lines 31-35 ignore the item on response.output_item.done, and line 91 drops response.function_call_arguments.done together with its arguments field.
    • vendor/serdes-ai-responses/src/client/mod.rs:661-693 (response_from_events) folds only PartDelta by output index, ignores PartEnd, and never compares the folded parts with the terminal response.output.
    • src/adapter.rs:65-68 passes the raw string through unchanged, so "" reaches the agent.
    • src/agent/tool_validation.rs:20-31 rejects it, and src/agent/tool_round.rs:17-25 turns that into self.dead(..., "invalid-tool-call", ...), which ends the session. src/agent/tool_validation_tests.rs:218-225 (malformed_tool_args_still_fatal) asserts that this is fatal.

    An empty folded string means no non-empty argument delta reached that part. Neither the old nor the #330 ToolCallPartDelta::apply can produce "" from non-empty deltas. The two remaining explanations are (a) the provider sent the arguments only in the done or item events, which the fold discards, or (b) the model emitted empty arguments. The current fold cannot tell these apart because it throws away the done evidence. The consistency check in #331 would turn case (a) into a diagnosable contradiction, though the session would still end.

    Separately from provenance, it is still an open question whether an empty or unparseable argument string should end the session or go back to the model as a corrective tool error, the way unknown tool names now get charged corrective results (e481f675, #206). The model never sees a response in either case, so case (b) can repeat on every attempt. That is a policy decision; this comment does not propose relaxing the parse.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions