Workflow tool approval dialog falsely flags scripts with lines >128 chars as "hidden control characters"
Summary
Any script passed to the Workflow tool that contains a single physical line longer than ~128 characters (no special/control characters required — plain ASCII text) causes the tool call to fail with:
The permission handler returned updatedInput for Workflow that failed schema validation: [
{
"code": "custom",
"path": ["script"],
"message": "script contains control characters that would be hidden in the approval dialog"
}
]
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.
This happens even with no custom canUseTool callback, PermissionRequest hook, or permission-prompt-tool configured — reproduced in a plain session with default settings. The error message's framing ("this is a configuration issue in your ... hook") is misleading in this case; the built-in approval-dialog handling for the Workflow tool appears to be the actual source, not user configuration.
Minimal repro
Both invoked via Workflow({ scriptPath: "<file>" }), no other content in the file:
Fails (129-char single line, plain ASCII, no comments/strings needed to trigger it):
export const meta = { name: 'diagnostic-129', description: 'threshold test 129' }
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
log('passed')
return { ok: true }
(the // comment line above is exactly 129 characters)
Passes (identical script, comment line shortened to 128 characters):
export const meta = { name: 'diagnostic-128', description: 'threshold test 128' }
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
log('passed')
return { ok: true }
Bisected the exact boundary across several lengths (100/128/129/130/135/140/150/200/400/841 chars) — 128 always passes, 129+ always fails, regardless of file size, whether the line is a comment/string/code, and whether it contains any non-ASCII characters. Confirmed independent of:
- CRLF vs LF line endings
- File size (reproduced on both a 20-byte test file and a 67KB real workflow script)
- Unicode content (em dashes, box-drawing characters, arrows — none of these alone trigger it; only line length does)
- Invocation form (
{ name: '<predefined workflow>' }vs{ scriptPath: '<file>' }— both fail identically)
128 is a strong hint the approval-dialog code processes the script in a fixed 128-byte/char chunk for display and mishandles a line that has no newline within that window (likely inserting some marker/padding when it can't find a break point, which then fails its own "no hidden control characters" self-check).
Impact
Any real workflow script with normal-length comments, long descriptive strings/prompts, or long single-line object literals (very common — e.g. long JSDoc-style banners, embedded LLM prompt text) will hit this and the Workflow tool becomes entirely unusable for that script until every line is manually reflowed under 128 characters.
Environment
- Claude Code CLI, reproduced in a plain (non-customized) session — no custom hooks/hooks.json entries targeting
Workflow, nopermission-prompt-toolconfigured. - Windows 10, Git Bash / PowerShell.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗