{"record":{"id":"61c9d9368c5674f5","repo":"coleam00/Archon","slug":"ref-references-node-nodeid-but-no-node-61c9d9","errorCode":null,"errorMessage":"'${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).","messagePattern":"'(.+?)' references node '(.+?)', 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\\.(.+?) Fix the id, or ensure '(.+?)' runs first \\(e\\.g\\. add it to depends_on\\)\\.","errorType":"exception","errorClass":"OutputRefError","httpStatus":null,"severity":"error","filePath":"packages/workflows/src/dag-executor.ts","lineNumber":388,"sourceCode":"    // Same loud posture (and hint shape) as the text splice in executor-shared.\n    const known = runInputs ? Object.keys(runInputs) : [];\n    const hint = similarNodeIds(name, known);\n    const suffix =\n      hint.length > 0\n        ? ` Did you mean ${hint.map(h => `$INPUTS.${h}`).join(', ')}?`\n        : known.length > 0\n          ? ` Available inputs: ${known.map(k => `$INPUTS.${k}`).join(', ')}.`\n          : ' This run has no declared inputs.';\n    throw new Error(`Unknown input '$INPUTS.${name}'.${suffix}`);\n  }\n  const wholeRef = parseWholeOutputRef(rawValue);\n  if (wholeRef !== undefined) {\n    const producer = ctx.nodeOutputs.get(wholeRef.nodeId);\n    if (producer !== undefined) {\n      return wholeRefLogicalValue(producer, wholeRef.nodeId, wholeRef.field);\n    }\n    if (wholeRef.field !== undefined) {\n      throw new OutputRefError(\n        wholeRef.nodeId,\n        wholeRef.field,\n        'unknown-node',\n        similarNodeIds(wholeRef.nodeId, ctx.nodeOutputs.keys())\n      );\n    }\n    if (strictWholeRef) {\n      const candidates = similarNodeIds(wholeRef.nodeId, ctx.nodeOutputs.keys());\n      const hint =\n        candidates.length > 0 ? ` Did you mean: ${candidates.map(c => `'${c}'`).join(', ')}?` : '';\n      throw new Error(\n        `Binding value '$${wholeRef.nodeId}.output' references node '${wholeRef.nodeId}', ` +\n          'but no node with that id has produced output at this point — the id is either ' +\n          'unknown (a typo) or belongs to a node that has not run before this reference.' +\n          `${hint} Fix the id, or add '${wholeRef.nodeId}' to depends_on.`\n      );\n    }\n    // Lenient legacy surface: fall through to the template path, which resolves the","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/workflows/src/dag-executor.ts#L370-L406","documentation":"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.","triggerScenarios":"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.","commonSituations":"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:.","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."],"exampleFix":"// before\nwith:\n  report: '$analisis.output.summary'   # typo'd producer\n// after\nwith:\n  report: '$analysis.output.summary'\ndepends_on: [analysis]","handlingStrategy":"validation","validationCode":"function validateFieldRef(ref: string, knownNodeIds: Set<string>): string | null {\n  const m = /^\\$([A-Za-z0-9_-]+)\\.output\\.([A-Za-z0-9_-]+)$/.exec(ref);\n  if (!m) return null; // not a whole field ref; other validation applies\n  return knownNodeIds.has(m[1]) ? null : `Unknown node id '${m[1]}' in '${ref}'`;\n}","typeGuard":null,"tryCatchPattern":"try {\n  runWorkflow(wf);\n} catch (e) {\n  if (e instanceof OutputRefError && e.reason === 'unknown-node') {\n    console.error(`Bad node ref '${e.nodeId}' (field '${e.field}'). Did you mean: ${e.similar.join(', ')}?`);\n  } else throw e;\n}","preventionTips":["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."],"tags":["workflow","node-output-reference","dependency-ordering","typo"],"backgroundTag":"unknown-node-output-reference","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}