[BUG] workflow subagents receive a substituted tool input, making every parameterized tool call fail schema validation
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Bug: workflow subagents receive a substituted tool input, making every parameterized tool call fail schema validation
Environment
- Claude Code 2.1.220
- Node v22.22.2, Linux
- Claude Code on the web (remote execution environment / SDK harness)
- Occurs in subagents spawned by the
Workflowtool. The main session is unaffected.
Summary
Inside workflow subagents, tool calls intermittently fail because the input the model emitted is replaced with a different object before schema validation. The model's input is well-formed — the error message itself confirms this ("The tool input from the model was valid"). The affected agent can then perform no work at all: every Read, Bash, Grep, Glob, and ToolSearch call fails, and the agent eventually dies on the StructuredOutput retry cap.
In one run this produced 202 occurrences across 12 subagents, which burned ~484k tokens and ~10.6 minutes of wall clock to accomplish nothing.
Symptom A — parameterized tools lose their required parameters
<tool_use_error>The permission handler returned updatedInput for Bash that failed schema validation:
Bash failed due to the following issue:
The required parameter `command` is missing
This is a configuration issue in your canUseTool callback, PermissionRequest hook, or
permission-prompt tool — updatedInput must satisfy the tool's input schema.
The tool input from the model was valid.</tool_use_error>
Identical errors for Read (file_path missing), Grep / Glob (pattern missing), ToolSearch (query missing).
Breakdown from a single affected run:
| Tool | Occurrences |
|---|---|
| Read | 66 |
| Bash | 63 |
| Grep | 16 |
| Glob | 15 |
| (empty tool name) | 15 |
| ToolSearch | 9 |
| Total | 202 |
Note the 15 occurrences where the tool name renders as empty — possibly a related symptom.
Symptom B — StructuredOutput fails the same way, and this one pinpoints the cause
The workflow used agent(prompt, { schema }). The subagent emitted a fully schema-conformant call:
// keys actually present in the model's tool_use input:
["correctedSeverity", "deliberateDeferral", "evidence", "isReal", "rationale", "stillApplies", "suggestedFix"]
The schema's five required properties were isReal, stillApplies, correctedSeverity, rationale, evidence — all present. Yet validation returned:
Output does not match required schema:
root: must have required property 'isReal',
root: must have required property 'stillApplies',
root: must have required property 'correctedSeverity',
root: must have required property 'rationale',
root: must have required property 'evidence',
root: must NOT have additional properties,
root: must NOT have additional properties,
root: must NOT have additional properties
So the validator saw none of the 7 keys the model sent, and instead saw exactly 3 keys that are not in the schema.
Likely root cause
The two symptoms are consistent with one defect: the permission layer's own response envelope is being passed to the tool/validator in place of the model's input.
- A ~3-key envelope (something shaped like
{ behavior, updatedInput, ... }) explains Symptom B exactly: zero schema properties present, three additional properties rejected. - The same substitution explains Symptom A: an envelope has no
command/file_path/pattern, so each tool reports its required parameter missing.
That is, updatedInput appears to be set to the wrapper object rather than to the inner input payload.
Frequency and what it does not correlate with
Intermittent — roughly one run in three completed healthily. It is not model-linked:
| Run | Subagent model | Permission errors | Outcome |
|---|---|---|---|
| A | claude-fable-5 | 0 | 16/16 agents succeeded |
| B | claude-fable-5 | 60 | all 5 agents failed |
| C | claude-opus-5 | 202 | all 12 agents failed |
The same model appears on both a clean run and a failing run, so switching models is not a workaround.
There is no PermissionRequest hook and no settings.json / settings.local.json in either the project or the user config directory, so this is not user hook configuration — it points at the canUseTool callback in the SDK harness that spawns workflow subagents.
Impact
- The subagent cannot read a single byte, so it produces no analysis.
- It exhausts the
StructuredOutputretry cap (5) and dies withTelemetrySafeError: StructuredOutput retry cap (5) exceeded. - The parent workflow reports every agent as failed after substantial token spend.
Secondary risk worth flagging: a workflow that post-processes verdicts can silently mislabel these failures. In our case an earlier script bucketed findings with !result.verdict?.isReal, so agents that died this way were reported as "refuted" — i.e. actively dismissed as non-issues — rather than "unverified". Notably, the subagents themselves handled this correctly: they attempted to return rationale: "UNVERIFIED due to tool failure; not a refutation", but that call was itself blocked by this bug, so the honest signal never escaped.
Suggested fix
In the subagent permission path, ensure updatedInput is assigned the inner tool-input payload rather than the permission-decision wrapper — and consider failing loudly if updatedInput does not validate against the tool schema, instead of forwarding it to the tool.
Reproduction notes
Not reliably reproducible on demand due to the intermittency. Occurs with Workflow running ~12 concurrent subagents, each using agent(prompt, { schema }) with a JSON Schema containing required and additionalProperties: false.
What Should Happen?
subagents should run full verification and report back without error
Error Messages/Logs
Steps to Reproduce
Bug: workflow subagents receive a substituted tool input, making every parameterized tool call fail schema validation
Environment
- Claude Code 2.1.220
- Node v22.22.2, Linux
- Claude Code on the web (remote execution environment / SDK harness)
- Occurs in subagents spawned by the
Workflowtool. The main session is unaffected.
Summary
Inside workflow subagents, tool calls intermittently fail because the input the model emitted is replaced with a different object before schema validation. The model's input is well-formed — the error message itself confirms this ("The tool input from the model was valid"). The affected agent can then perform no work at all: every Read, Bash, Grep, Glob, and ToolSearch call fails, and the agent eventually dies on the StructuredOutput retry cap.
In one run this produced 202 occurrences across 12 subagents, which burned ~484k tokens and ~10.6 minutes of wall clock to accomplish nothing.
Symptom A — parameterized tools lose their required parameters
<tool_use_error>The permission handler returned updatedInput for Bash that failed schema validation:
Bash failed due to the following issue:
The required parameter `command` is missing
This is a configuration issue in your canUseTool callback, PermissionRequest hook, or
permission-prompt tool — updatedInput must satisfy the tool's input schema.
The tool input from the model was valid.</tool_use_error>
Identical errors for Read (file_path missing), Grep / Glob (pattern missing), ToolSearch (query missing).
Breakdown from a single affected run:
| Tool | Occurrences |
|---|---|
| Read | 66 |
| Bash | 63 |
| Grep | 16 |
| Glob | 15 |
| (empty tool name) | 15 |
| ToolSearch | 9 |
| Total | 202 |
Note the 15 occurrences where the tool name renders as empty — possibly a related symptom.
Symptom B — StructuredOutput fails the same way, and this one pinpoints the cause
The workflow used agent(prompt, { schema }). The subagent emitted a fully schema-conformant call:
// keys actually present in the model's tool_use input:
["correctedSeverity", "deliberateDeferral", "evidence", "isReal", "rationale", "stillApplies", "suggestedFix"]
The schema's five required properties were isReal, stillApplies, correctedSeverity, rationale, evidence — all present. Yet validation returned:
Output does not match required schema:
root: must have required property 'isReal',
root: must have required property 'stillApplies',
root: must have required property 'correctedSeverity',
root: must have required property 'rationale',
root: must have required property 'evidence',
root: must NOT have additional properties,
root: must NOT have additional properties,
root: must NOT have additional properties
So the validator saw none of the 7 keys the model sent, and instead saw exactly 3 keys that are not in the schema.
Likely root cause
The two symptoms are consistent with one defect: the permission layer's own response envelope is being passed to the tool/validator in place of the model's input.
- A ~3-key envelope (something shaped like
{ behavior, updatedInput, ... }) explains Symptom B exactly: zero schema properties present, three additional properties rejected. - The same substitution explains Symptom A: an envelope has no
command/file_path/pattern, so each tool reports its required parameter missing.
That is, updatedInput appears to be set to the wrapper object rather than to the inner input payload.
Frequency and what it does not correlate with
Intermittent — roughly one run in three completed healthily. It is not model-linked:
| Run | Subagent model | Permission errors | Outcome |
|---|---|---|---|
| A | claude-fable-5 | 0 | 16/16 agents succeeded |
| B | claude-fable-5 | 60 | all 5 agents failed |
| C | claude-opus-5 | 202 | all 12 agents failed |
The same model appears on both a clean run and a failing run, so switching models is not a workaround.
There is no PermissionRequest hook and no settings.json / settings.local.json in either the project or the user config directory, so this is not user hook configuration — it points at the canUseTool callback in the SDK harness that spawns workflow subagents.
Impact
- The subagent cannot read a single byte, so it produces no analysis.
- It exhausts the
StructuredOutputretry cap (5) and dies withTelemetrySafeError: StructuredOutput retry cap (5) exceeded. - The parent workflow reports every agent as failed after substantial token spend.
Secondary risk worth flagging: a workflow that post-processes verdicts can silently mislabel these failures. In our case an earlier script bucketed findings with !result.verdict?.isReal, so agents that died this way were reported as "refuted" — i.e. actively dismissed as non-issues — rather than "unverified". Notably, the subagents themselves handled this correctly: they attempted to return rationale: "UNVERIFIED due to tool failure; not a refutation", but that call was itself blocked by this bug, so the honest signal never escaped.
Suggested fix
In the subagent permission path, ensure updatedInput is assigned the inner tool-input payload rather than the permission-decision wrapper — and consider failing loudly if updatedInput does not validate against the tool schema, instead of forwarding it to the tool.
Reproduction notes
Not reliably reproducible on demand due to the intermittency. Occurs with Workflow running ~12 concurrent subagents, each using agent(prompt, { schema }) with a JSON Schema containing required and additionalProperties: false.
Claude Model
Other
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
Claude Code 2.1.220
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
_No response_
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗