Workflow tool: args object delivered to script as JSON string (schema's untyped `args` → model emits string; dup of #72248) — bug 2 in original report retracted

Open 💬 4 comments Opened Jul 14, 2026 by mini920325-gif

Environment

  • Claude Code version: 2.1.201 (native install, macOS / Darwin 25.5.0)
  • Session model: claude-fable-5
  • Both bugs observed in a single Workflow run (52 subagents, dynamic script via the Workflow tool), reproduced consistently within that session.

Two related bugs in the Workflow/background-task subsystem, found in one run. Happy to split into separate issues if preferred.

---

Bug 1: Workflow args object is delivered to the script as a JSON string

The Workflow tool docs state:

args: any — the value passed as Workflow's args input, verbatim. Pass arrays/objects as actual JSON values in the tool call, NOT as a JSON-encoded string.

The model passed args as a proper JSON object in the tool call:

{ "script": "...", "args": { "skills": [ {"name": "...", "path": "..."}, ... ] } }

But inside the script, args arrived as a JSON-encoded string, so args.skills was undefined and the run crashed immediately:

TypeError: pipeline() expects an array as the first argument
    at <anonymous> (/$bunfs/root/src/entrypoints/cli.js:6602:4054)

The failure notification's recovery snippet also shows the harness itself re-encoding args as a string:

Workflow({scriptPath: '...', resumeFromRunId: '...', args: "{\"skills\": [{\"name\": ...

Workaround (confirmed working): defensive parse at the top of the script:

const input = typeof args === 'string' ? JSON.parse(args) : args

Expected: args reaches the script as the same JSON value passed in the tool call.

---

Bug 2: Premature completed task-notification while the workflow is still running; output file empty at that point

Timeline of a 52-agent workflow run (task id w1tfx6dkg):

  1. T+9min — a <task-notification> fired with status: completed, claiming agents_done: 52 and duration_ms: 541317, including a Result: preview and pointing to the task output file.
  2. At that moment the output file was 0 bytes (wc -c → 0), the workflow journal (journal.jsonl) contained only ~10 of 52 agent results, and TaskOutput(block:false) returned status: running — i.e. the notification was false.
  3. The journal kept growing for another ~15 minutes.
  4. T+24min — a second, correct notification fired (duration_ms: 1447553, agents_done: 52), and the output file was then written correctly (325 KB, valid {summary, agentCount, logs, result} JSON).

Inconsistencies in the premature notification:

  • status: completed while the run was still executing (contradicted by TaskOutput and by the still-growing journal)
  • agents_done: 52 when only ~10 results existed in the journal
  • subagent_tokens: 1082815 vs the final 4640892 (so the "done" count could not have been real)
  • output-file path provided, but the file was empty

Impact: a model (or user tooling) that trusts the first notification reads an empty/partial result and may conclude the workflow produced nothing. The TaskOutput re-check is a viable workaround, but the notification contract ("you will be notified when it completes") is broken by the early false-positive event.

Expected: exactly one completed notification, emitted after the run actually finishes and the output file is flushed.

---

Notes

  • Both bugs were worked around in-session (defensive JSON.parse; re-verifying completion via TaskOutput + journal growth), so this is a report, not a blocker.
  • The per-agent results in journal.jsonl were complete and correct in both runs — only the args passing and the notification/output-file timing misbehaved.

🤖 Filed via Claude Code on behalf of the account owner.

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗