Problem
When a bash: or script: node fails, the executor surfaces an error message that includes the entire substituted script body inline (often 1000+ chars), wrapping the actual diagnostic in noise. For an agent (or human) trying to figure out what went wrong, the signal is buried.
Example excerpt from a real failed script: node (truncated for brevity):
[format-changelog] Failed: Script node 'format-changelog' failed: Command failed: bun --no-env-file -e import { mkdirSync, writeFileSync } from \"node:fs\";
import { join } from \"node:path\";
const cl = JSON.parse(String.raw`{\"summary\":\"Binary path auto-detection for Claude/Codex...\",\"added\":[\"Automatic detection of canonical install paths for the Claude Code and Codex binaries — `claudeBinaryPath`/`codexBinaryPath` no longer need to be set manually in most environments (#1361)\"],...}`);
... [the entire 50-line script repeated three times — once in err.message, once in err.stack, once in err.cmd] ...
4 | r the Claude Code and Codex binaries — `claudeBinaryPath`/`codexBinaryPath` no longer need to be set manually in most
^
error: Expected \")\" but found \"claudeBinaryPath\"
at /Users/rasmus/Projects/cole/Archon/[eval]:4:241
The actually useful part — Expected \")\" but found \"claudeBinaryPath\" at [eval]:4:241 — is one line at the end. The script body is reproduced ~3x in the JSON log entry (once in err.message, once in err.stack, once in err.cmd), and again in the human-readable [node-id] Failed: ... output line.
Why this matters more for Archon than for typical CLIs
Archon's value prop is agents authoring and running workflows. When a workflow fails, the most common follow-up is the agent reading the error and editing the YAML. The current format trains agents to:
- Skip past the noise looking for the real error
- Sometimes miss the real error entirely (it's often after 2KB of script-body repetition)
- Burn context-window tokens that could go toward the fix
A self-correcting agent loop ("workflow failed → AI reads error → AI patches YAML → re-run") is much more reliable when the error is concise and points at the failing line.
Proposed direction
The principle: error messages should be informative enough that an agent running Archon can self-correct the workflow without reading the script body.
Concrete changes that would help (sketched, not prescriptive):
- Don't repeat the script body 3× in the log entry.
err.cmd contains it; err.message and err.stack should reference "node 'format-changelog' script (see err.cmd)" instead of inlining it again.
- Surface stderr first. The actually-useful diagnostic from
bun/the failed binary is always in stderr. Lead with stderr, demote the script body to a separate field or a debug-level log.
- For
script: nodes specifically, parse the stderr for at [eval]:LINE:COL and emit a structured failedAt: { line, col, snippet } field. Agents can then jump directly to the right line in the YAML.
- In the human-readable
[node-id] Failed: ... output, print just the diagnostic summary ("Script syntax error at line 4 col 241: Expected ')' but found 'claudeBinaryPath'") and keep the verbose stack trace in the JSON log.
- Optional: include a hint when a recognizable pattern matches. For the case above, the failure was triggered by a backtick in the substituted
\$nodeId.output. A heuristic check ("substituted value contained backticks; this may have terminated the JS template literal") would shortcut a real category of mistakes.
Repro
- Author a
script: node that consumes `String.raw\`$other-node.output\`` where the upstream output is AI-generated content containing backticks (any markdown code spans).
- Run the workflow.
- Observe the failure log: the actual JS syntax error is buried in ~1KB of repeated script body.
Found while
Building a custom `archon-release` workflow during a workshop prep session. The failing pattern was the canonical `String.raw\`$nodeId.output\`` substitution shown in the docs example (`.claude/skills/archon/examples/dag-workflow.yaml`), which is safe for `gh`-CLI JSON output but breaks for AI prompt outputs.
Problem
When a
bash:orscript:node fails, the executor surfaces an error message that includes the entire substituted script body inline (often 1000+ chars), wrapping the actual diagnostic in noise. For an agent (or human) trying to figure out what went wrong, the signal is buried.Example excerpt from a real failed
script:node (truncated for brevity):The actually useful part —
Expected \")\" but found \"claudeBinaryPath\" at [eval]:4:241— is one line at the end. The script body is reproduced ~3x in the JSON log entry (once inerr.message, once inerr.stack, once inerr.cmd), and again in the human-readable[node-id] Failed: ...output line.Why this matters more for Archon than for typical CLIs
Archon's value prop is agents authoring and running workflows. When a workflow fails, the most common follow-up is the agent reading the error and editing the YAML. The current format trains agents to:
A self-correcting agent loop ("workflow failed → AI reads error → AI patches YAML → re-run") is much more reliable when the error is concise and points at the failing line.
Proposed direction
The principle: error messages should be informative enough that an agent running Archon can self-correct the workflow without reading the script body.
Concrete changes that would help (sketched, not prescriptive):
err.cmdcontains it;err.messageanderr.stackshould reference "node 'format-changelog' script (see err.cmd)" instead of inlining it again.bun/the failed binary is always in stderr. Lead with stderr, demote the script body to a separate field or a debug-level log.script:nodes specifically, parse the stderr forat [eval]:LINE:COLand emit a structuredfailedAt: { line, col, snippet }field. Agents can then jump directly to the right line in the YAML.[node-id] Failed: ...output, print just the diagnostic summary ("Script syntax error at line 4 col 241: Expected ')' but found 'claudeBinaryPath'") and keep the verbose stack trace in the JSON log.\$nodeId.output. A heuristic check ("substituted value contained backticks; this may have terminated the JS template literal") would shortcut a real category of mistakes.Repro
script:node that consumes `String.raw\`$other-node.output\`` where the upstream output is AI-generated content containing backticks (any markdown code spans).Found while
Building a custom `archon-release` workflow during a workshop prep session. The failing pattern was the canonical `String.raw\`$nodeId.output\`` substitution shown in the docs example (`.claude/skills/archon/examples/dag-workflow.yaml`), which is safe for `gh`-CLI JSON output but breaks for AI prompt outputs.