{"record":{"id":"24b61e1f8e7ffbdb","repo":"coleam00/Archon","slug":"node-consumerid-binding-name-an-object","errorCode":null,"errorMessage":"Node '${consumerId}' binding '${name}': an object value must be a binding directive { from: '$node.output[.field]', if_skipped?: <value> }. Use a string, number, boolean, null, or array for a literal value.","messagePattern":"Node '(.+?)' binding '(.+?)': an object value must be a binding directive (.+?)\\. Use a string, number, boolean, null, or array for a literal value\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/workflows/src/dag-executor.ts","lineNumber":456,"sourceCode":" * for that simulator only; it must resolve bindings with THIS function so preview\n * and execution cannot drift (#2637 R2).\n */\nexport function resolveNodeBindings(\n  consumerId: string,\n  withMap: Record<string, JsonValue | BindingDirective>,\n  ctx: ShellInputContext,\n  runInputs: Record<string, JsonValue> | undefined\n): Record<string, JsonValue> {\n  const resolved: Record<string, JsonValue> = {};\n  for (const [name, rawValue] of Object.entries(withMap)) {\n    if (isBindingDirective(rawValue)) {\n      resolved[name] = resolveBindingDirective(consumerId, name, rawValue, ctx);\n      continue;\n    }\n    if (typeof rawValue === 'object' && rawValue !== null && !Array.isArray(rawValue)) {\n      // The loader rejects this shape at load time; programmatic definitions can\n      // still reach here, so keep the failure loud and actionable.\n      throw new Error(\n        `Node '${consumerId}' binding '${name}': an object value must be a binding directive ` +\n          \"{ from: '$node.output[.field]', if_skipped?: <value> }. Use a string, number, \" +\n          'boolean, null, or array for a literal value.'\n      );\n    }\n    resolved[name] = resolveWorkflowValue(rawValue, ctx, runInputs, true);\n  }\n  return resolved;\n}\n\nfunction resolveBindingDirective(\n  consumerId: string,\n  name: string,\n  directive: BindingDirective,\n  ctx: ShellInputContext\n): JsonValue {\n  const ref = parseWholeOutputRef(directive.from);\n  if (ref === undefined) {","sourceCodeStart":438,"sourceCodeEnd":474,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/workflows/src/dag-executor.ts#L438-L474","documentation":"resolveNodeBindings accepts either a plain literal value or an explicit binding directive object { from, if_skipped? } for each with: entry. A plain object that is neither (a binding directive shape was not recognized) is rejected. The YAML loader normally rejects this at load time, but programmatic workflow definitions can reach the executor, so the failure is kept loud and actionable.","triggerScenarios":"Passing a Record/object as a with: value through a programmatically constructed workflow definition (API or code that builds the withMap) where the object lacks the recognized 'from' key or directive shape.","commonSituations":"Building workflow JSON in TypeScript and nesting a config object (e.g. { model: ..., prompt: ... }) as a binding value expecting it to pass through; typos like 'from_' or 'source:' instead of 'from:'; loader bypass in tests or the dry-run simulator path.","solutions":["Wrap the object in a binding directive: { from: '$node.output[.field]', if_skipped?: <value> }.","Replace the object with a literal (string, number, boolean, null, or array) if a static value is intended.","Validate the definition through the loader before execution so the error surfaces at load time with richer context."],"exampleFix":"// before\nwith:\n  config:\n    model: fast\n    prompt: hello\n// after\nwith:\n  config: '{\"model\":\"fast\",\"prompt\":\"hello\"}'   # literal, or:\n  config:\n    from: '$build_config.output'","handlingStrategy":"validation","validationCode":"function isBindingDirective(v: unknown): boolean {\n  return typeof v === 'object' && v !== null && !Array.isArray(v) && 'from' in v;\n}\nfunction validateWithValue(v: unknown): string | null {\n  if (typeof v === 'object' && v !== null && !Array.isArray(v) && !isBindingDirective(v))\n    return 'Object with: values must be { from: ... } directives or literals';\n  return null;\n}","typeGuard":"function isBindingDirective(v: unknown): v is { from: string; if_skipped?: unknown } {\n  return typeof v === 'object' && v !== null && !Array.isArray(v) && typeof (v as any).from === 'string';\n}","tryCatchPattern":"try {\n  runWorkflow(wf);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('must be a binding directive')) {\n    console.error('Invalid with: value shape — use { from } or a literal:', e.message);\n  } else throw e;\n}","preventionTips":["Run every definition through the loader before execution — it rejects this shape with better context.","Serialize nested config objects to JSON strings when a literal object payload is needed.","Add a type on programmatic builders so with: values are JsonValue | BindingDirective, not any."],"tags":["workflow","binding","validation","schema-shape"],"backgroundTag":"invalid-binding-directive","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}