coleam00/Archon · error · OutputRefError
'${ref}' references node '${nodeId}', but no node with that
Error message
'${ref}' references node '${nodeId}', but no node with that id has produced output at this point — the id is either unknown (a typo) or belongs to a node that has not run before this reference.${hint} Fix the id, or ensure '${nodeId}' runs first (e.g. add it to depends_on). What it means
resolveWorkflowValue resolves a string like '$node.output.field' to an upstream node's logical output. When the referenced nodeId has no entry in the run's nodeOutputs map at resolution time, and the ref targets a specific field, the executor throws an OutputRefError with reason 'unknown-node' plus similar-id suggestions. The library throws it because a field-level reference cannot be resolved lazily — the producer either doesn't exist or hasn't run yet.
Source
Thrown at packages/workflows/src/dag-executor.ts:388
// Same loud posture (and hint shape) as the text splice in executor-shared.
const known = runInputs ? Object.keys(runInputs) : [];
const hint = similarNodeIds(name, known);
const suffix =
hint.length > 0
? ` Did you mean ${hint.map(h => `$INPUTS.${h}`).join(', ')}?`
: known.length > 0
? ` Available inputs: ${known.map(k => `$INPUTS.${k}`).join(', ')}.`
: ' This run has no declared inputs.';
throw new Error(`Unknown input '$INPUTS.${name}'.${suffix}`);
}
const wholeRef = parseWholeOutputRef(rawValue);
if (wholeRef !== undefined) {
const producer = ctx.nodeOutputs.get(wholeRef.nodeId);
if (producer !== undefined) {
return wholeRefLogicalValue(producer, wholeRef.nodeId, wholeRef.field);
}
if (wholeRef.field !== undefined) {
throw new OutputRefError(
wholeRef.nodeId,
wholeRef.field,
'unknown-node',
similarNodeIds(wholeRef.nodeId, ctx.nodeOutputs.keys())
);
}
if (strictWholeRef) {
const candidates = similarNodeIds(wholeRef.nodeId, ctx.nodeOutputs.keys());
const hint =
candidates.length > 0 ? ` Did you mean: ${candidates.map(c => `'${c}'`).join(', ')}?` : '';
throw new Error(
`Binding value '$${wholeRef.nodeId}.output' references node '${wholeRef.nodeId}', ` +
'but no node with that id has produced output at this point — the id is either ' +
'unknown (a typo) or belongs to a node that has not run before this reference.' +
`${hint} Fix the id, or add '${wholeRef.nodeId}' to depends_on.`
);
}
// Lenient legacy surface: fall through to the template path, which resolves theView on GitHub (pinned to 0773b97458)
Solutions
- Fix the node id in the reference (check the 'Did you mean' candidates in the error hint).
- Add the producer to the consumer's depends_on so its output exists before binding resolution.
- If the producer is on a possibly-skipped branch, use a binding directive { from: '$node.output.field', if_skipped: <default> } instead of a bare string.
Example fix
// before with: report: '$analisis.output.summary' # typo'd producer // after with: report: '$analysis.output.summary' depends_on: [analysis]
Defensive patterns
Strategy: validation
Validate before calling
function validateFieldRef(ref: string, knownNodeIds: Set<string>): string | null {
const m = /^\$([A-Za-z0-9_-]+)\.output\.([A-Za-z0-9_-]+)$/.exec(ref);
if (!m) return null; // not a whole field ref; other validation applies
return knownNodeIds.has(m[1]) ? null : `Unknown node id '${m[1]}' in '${ref}'`;
} Try / catch
try {
runWorkflow(wf);
} catch (e) {
if (e instanceof OutputRefError && e.reason === 'unknown-node') {
console.error(`Bad node ref '${e.nodeId}' (field '${e.field}'). Did you mean: ${e.similar.join(', ')}?`);
} else throw e;
} Prevention
- List every referenced producer in the consumer's depends_on.
- Keep node ids verbatim from one source (constant or generated) instead of hand-typing refs.
- Dry-run the workflow before executing; the simulator resolves bindings the same way.
- Validate the definition through the loader before runs.
When it happens
Trigger: Resolving a 'with:' binding or node value whose string is exactly '$producer.output.field' (parseWholeOutputRef matched, field is defined) while ctx.nodeOutputs has no entry for the producer id — e.g. a typo'd node id, or the producer is not in depends_on and executes after the consumer.
Common situations: Renaming a node in YAML without updating downstream $refs; forgetting to list the producer in depends_on so it hasn't run when the consumer's bindings resolve; programmatically-built workflow definitions bypassing loader validation; referencing a node in a different branch guarded by when:.
Related errors
- Binding value '$${wholeRef.nodeId}.output' references node '
- Node '${consumerId}' binding '${name}' reads '${directive.fr
- Cannot execute run '${detachedPreCreatedRun.id}': it belongs
- Dry-run failed; missing stubs: ${blockingMissingStubs.join('
- result.error
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/61c9d9368c5674f5.
Report an issue: GitHub.