Workflow tool: permission handler false-positives on 'control characters' for plain-ASCII scripts as small as ~2-5KB
Description
The Workflow tool's permission-approval handler rejects the vast majority of non-trivial workflow scripts 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"
}
]
The scripts in question are plain ASCII with no control characters (verified — no unicode, no non-printable bytes). The rejection is a false positive, and it triggers on payloads far smaller than "a large script" — small enough that it makes the Workflow tool effectively unusable for any script that embeds a non-trivial amount of literal text (e.g. prompt/context content for subagents).
Reproduction
Bisected with a series of throwaway scripts, each doing nothing but returning a static value (zero agent() calls, so no subagent cost was involved in reproducing this):
| Test | Total script size | Longest single string literal | Result |
|---|---|---|---|
| Minimal control (no padding) | ~200B | 0 chars | PASS |
| Single string literal, 98 chars | ~350B | 98 | PASS |
| Single string literal, 145 chars | ~400B | 145 | PASS |
| Single string literal, ~200 chars | ~430B | 200 | FAIL |
| Many short string literals (30 lines) | ~2.2KB | ~70 | PASS |
| Many short string literals (47 lines) | ~5.2KB | ~100 | FAIL |
| Many short string literals (95 lines) | ~10KB | ~100 | FAIL |
| Many short string literals (285 lines) | ~30KB | ~100 | FAIL |
| Many short string literals (700 lines) | ~73KB | ~100 | FAIL |
This points to (at least) two independent triggers:
- A single string literal longer than roughly 150–200 characters fails, even inside an otherwise-trivial ~400-byte script.
- Total script size fails somewhere between ~2.2KB and ~5.2KB, independent of (1) — restructuring a large payload as many short string literals instead of one long one does not avoid this second trigger.
All test scripts were pure ASCII, contained no unicode, no non-printable/control bytes, and no unusual characters beyond standard JS syntax (quotes, brackets, commas). Example of a script that fails (minimal repro, single literal):
export const meta = {
name: 'smoke-test',
description: 'minimal repro',
phases: [{ title: 'Smoke test' }],
}
phase('Smoke test')
const L = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
return { ok: true }
(200-char literal of the letter "a" — fails; the same script with a 145-char literal succeeds.)
Impact
This makes the Workflow tool unusable for its documented purpose in any case where a subagent needs a non-trivial amount of literal context embedded in the script (e.g. a document excerpt, a data sample, prompt template text) — which is a normal and expected use case per the tool's own documentation (e.g. its guidance around assembling a "context block" for spawned agents). We first hit this as a real blocker while trying to orchestrate a batch review process via Workflow, where each subagent needed tens of KB of context text; every attempt was rejected regardless of how the script was structured.
Environment
- Claude Code CLI,
claude-in-chrome/harness-integratedWorkflowtool - Platform: Windows 11, PowerShell/Git Bash
- Reproduced via
Workflow({ scriptPath: <path to .js file> })
Expected behavior
A plain-ASCII script with no actual control characters should not be rejected as "containing control characters that would be hidden in the approval dialog." If there is a legitimate size-based safeguard intended here, it should not trigger at ~2-5KB — that is far below any reasonable script size for real orchestration use cases — and the error message should reflect the actual reason (e.g. "script exceeds N bytes") rather than a misleading "control characters" message when none are present.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗