{"record":{"id":"78edd70af20fac51","repo":"coleam00/Archon","slug":"binding-value-wholeref-nodeid-output-referen","errorCode":null,"errorMessage":"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.","messagePattern":"Binding value '\\$(.+?)\\.output' 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 add '(.+?)' to depends_on\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/workflows/src/dag-executor.ts","lineNumber":399,"sourceCode":"  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\n    // unknown whole-text ref to '' with a warn — byte-identical to pre-#2637.\n  }\n  const { prompt: substituted } = substituteWorkflowVariables(\n    rawValue,\n    ctx.workflowRun.id,\n    ctx.workflowRun.user_message,\n    ctx.artifactsDir,\n    ctx.baseBranch,\n    ctx.docsDir,\n    ctx.issueContext,\n    undefined,","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/workflows/src/dag-executor.ts#L381-L417","documentation":"In strict whole-ref mode, resolveWorkflowValue throws when a string binding value '$node.output' (whole output, no field) points at a nodeId absent from nodeOutputs. Unlike the field case (445), the strict flag is set by the binding resolver (resolveNodeBindings), so this fires specifically for node-local with: bindings. The intent is to fail loudly rather than silently substitute an empty string through the legacy template path.","triggerScenarios":"A with: entry whose string is exactly '$producer.output' while the producer has no recorded output — unknown id, producer not in depends_on, or producer not yet executed when bindings resolve. Bare-string refs outside bindings go through the lenient legacy path and do not throw this.","commonSituations":"Copy-pasting a whole-output ref after renaming the producer; missing depends_on edge in hand-written or generated YAML; referencing a node in a parallel branch that is scheduled later; dry-run simulations with an incomplete nodeOutputs map.","solutions":["Correct the node id (use the 'Did you mean' candidates from the hint).","Add the producer to depends_on so it runs before the consumer resolves bindings.","Use the binding directive form with if_skipped when the producer may legitimately not run."],"exampleFix":"// before\nwith:\n  text: '$analizer.output'\n// after\nwith:\n  text:\n    from: '$analyzer.output'\n    if_skipped: ''\ndepends_on: [analyzer]","handlingStrategy":"validation","validationCode":"function validateWholeRefs(withMap: Record<string, unknown>, knownNodeIds: Set<string>): string[] {\n  const errs: string[] = [];\n  for (const [k, v] of Object.entries(withMap)) {\n    if (typeof v === 'string') {\n      const m = /^\\$([A-Za-z0-9_-]+)\\.output$/.exec(v);\n      if (m && !knownNodeIds.has(m[1])) errs.push(`with.${k}: unknown node '${m[1]}'`);\n    }\n  }\n  return errs;\n}","typeGuard":null,"tryCatchPattern":"try {\n  runWorkflow(wf);\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"has produced output at this point\")) {\n    console.error('Whole-output ref targets a missing/unrun node:', e.message);\n  } else throw e;\n}","preventionTips":["Use the binding directive form ({ from, if_skipped }) for refs on possibly-skipped branches.","Ensure depends_on edges cover every $node.output reference.","Never hand-build with: maps in code without a lint/validation pass.","Run the dry-run simulator to catch ordering issues cheaply."],"tags":["workflow","node-output-reference","binding","dependency-ordering"],"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"}