coleam00/Archon · error · OutputRefError
producer-not-run
producer-not-run
Error message
producer-not-run
What it means
resolveNodeOutputField resolves `$node.field` output references. When the producer node's state is `skipped` or `pending`, it has no output to read a field from, so the engine throws this typed OutputRefError instead of falling through to the schemaless path, which would misleadingly report 'not a JSON object' on empty output.
Source
Thrown at packages/workflows/src/output-ref.ts:342
}
}
/**
* Resolve `field` against a producer's `NodeOutput`. Returns the raw field value
* (callers stringify per their context), signals an intended empty, or throws
* `OutputRefError` for the strict cases. See the module doc for the full table.
*/
export function resolveNodeOutputField(
nodeOutput: NodeOutput,
nodeId: string,
field: string
): FieldResolution {
// A producer that did not run (skipped) or has not settled (pending) has no
// output to read a field from. Surface that directly rather than letting it
// fall through to the schemaless path and throw the misleading "not a JSON
// object" error on its empty output.
if (nodeOutput.state === 'skipped' || nodeOutput.state === 'pending') {
throw new OutputRefError(nodeId, field, 'producer-not-run');
}
// A failed producer never resolves a field, however JSON-shaped its leftover
// output looks (#2713): a loop_group's failure paths carry the last completed
// iteration's real, often-valid-JSON text, which would otherwise be read here
// as if the group had succeeded — the same class of bug #2696/#2710 fixed for
// the `{ from, if_skipped }` binding directive.
if (nodeOutput.state === 'failed') {
throw new OutputRefError(nodeId, field, 'producer-failed');
}
const declaredFields = 'declaredFields' in nodeOutput ? nodeOutput.declaredFields : undefined;
const structured = 'structuredOutput' in nodeOutput ? nodeOutput.structuredOutput : undefined;
const structuredObj = asPlainObject(structured);
// 1. Declared-schema producer — the declared property set IS the contract.
if (declaredFields !== undefined) {
if (!declaredFields.includes(field)) {View on GitHub (pinned to 0773b97458)
Solutions
- Guard the consumer with the same `if:` condition as the producer so both skip together.
- Use the `{ from: nodeId, if_skipped: <value> }` binding directive (or an explicit fallback) for `$node.output` reads.
- Use `$INPUTS` or a join node to supply a default when the producer may not run.
- Fix workflow ordering so the producer settles before the consumer substitutes refs.
Example fix
// before - id: consumer bash: echo "$analyze.summary" // after - id: consumer if: analyze.succeeded bash: echo "$analyze.summary"
Defensive patterns
Strategy: fallback
Validate before calling
// before scheduling the consumer, check producer state
const state = run.nodeOutputs[producerId]?.state;
if (state === 'skipped' || state === 'pending') {
skipConsumer(producerId); // or attach the same `if:` condition
} Type guard
function producerRan(o: { state: string }): o is { state: 'succeeded' | 'failed' } {
return o.state === 'succeeded' || o.state === 'failed';
} Try / catch
try {
const value = resolveNodeOutputField(nodeOutput, nodeId, field);
} catch (err) {
if (err instanceof OutputRefError && err.reason === 'producer-not-run') {
return defaultFor(field); // explicit, logged fallback
}
throw err;
} Prevention
- Give consumers that depend on a conditional producer the same `if:` condition.
- Use `{ from, if_skipped }`/fallback bindings instead of raw `$node.field` when a producer may be skipped.
- Do not reference nodes that run later in the topology.
- Review the run graph so every `$node.field` edge has a producer that always executes.
When it happens
Trigger: A consumer node's body references `$producer.field` while the producer was skipped (an `if:` condition did not hold) or is still pending at substitution time — e.g. referencing a node downstream of a skipped branch or reading a not-yet-settled node.
Common situations: Branching workflows where the consumer also needs an `if:` guard so it does not read from a skipped producer; missing `if_skipped`/fallback binding directives; wiring a consumer to a producer that joins later.
Related errors
- Node '${consumerId}' binding '${name}' reads '${directive.fr
- producer-failed
- not-in-schema
- unparseableReason(nodeOutput.output) (dynamic reason code fo
- missing-key
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/b2a122875f63e72f.
Report an issue: GitHub.