{"record":{"id":"94bf0b5bae1b8a40","repo":"coleam00/Archon","slug":"workflow-run-has-invalid-model-bindings-metadata","errorCode":null,"errorMessage":"Workflow run has invalid model_bindings metadata.","messagePattern":"Workflow run has invalid model_bindings metadata\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/workflows/src/model-validation.ts","lineNumber":512,"sourceCode":"  const value = metadata?.[RUN_MODEL_BINDINGS_METADATA_KEY];\n  if (value === undefined) return undefined;\n  const parsed = runModelBindingsMetadataSchema.safeParse(value);\n  if (!parsed.success) {\n    const path = parsed.error.issues[0]?.path ?? [];\n    const bindingName = typeof path[2] === 'string' ? path[2] : 'unknown';\n    if (path.includes('thinking')) {\n      throw new Error(`Model binding '${bindingName}' has invalid thinking options.`);\n    }\n    if (path.includes('effort')) {\n      throw new Error(`Model binding '${bindingName}' has an invalid effort.`);\n    }\n    if (path[0] === 'overrides' && (path[1] === 'tiers' || path[1] === 'aliases')) {\n      throw new Error(`Workflow run has invalid model_bindings ${path[1]} metadata.`);\n    }\n    if (path[0] === 'effective') {\n      throw new Error('Workflow run has invalid effective model bindings.');\n    }\n    throw new Error('Workflow run has invalid model_bindings metadata.');\n  }\n\n  const tiers = Object.fromEntries(\n    Object.entries(parsed.data.overrides.tiers ?? {}).map(([name, preset]) => [\n      name,\n      normalizePersistedOverridePreset(name, preset),\n    ])\n  );\n  const aliases = Object.fromEntries(\n    Object.entries(parsed.data.overrides.aliases ?? {}).map(([name, preset]) => [\n      name,\n      normalizePersistedOverridePreset(name, preset),\n    ])\n  );\n  for (const [name, preset] of Object.entries(parsed.data.effective.aliases)) {\n    assertValidPersistedPreset(name, preset);\n  }\n","sourceCodeStart":494,"sourceCodeEnd":530,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/workflows/src/model-validation.ts#L494-L530","documentation":"The engine failed to parse the `model_bindings` metadata persisted on a workflow run, or found a forbidden shape: overrides keyed by `tiers` or `aliases` are not valid at the run level, and `effective` bindings must never appear in run metadata (they are computed). This guard protects resumed runs from silently running with different models than the workflow intended.","triggerScenarios":"A run row (or rehydrated event payload) carries `model_bindings.overrides.tiers`, `model_bindings.overrides.aliases`, or `model_bindings.effective`, or the metadata blob otherwise fails the persistence schema in readRunModelBindingsMetadata during executeWorkflow/resume.","commonSituations":"Hand-editing the SQLite/Postgres runs table; resuming a run persisted by an older or newer binary that wrote a different metadata shape; a tool that copies 'effective' bindings back into run metadata; a bug in a custom migration.","solutions":["Remove `overrides.tiers`, `overrides.aliases`, and `effective` keys from the run's `model_bindings` metadata (only per-node overrides belong there), or delete and re-run the workflow so metadata is regenerated.","Check which binary version wrote the run; resume with the same version that created it.","Set model tiers/aliases through supported config (.archon/config.yaml tiers.*, `archon ai tier set`) instead of injecting run metadata.","If the run row is unrecoverable, start a fresh run; the workflow definition remains the source of truth."],"exampleFix":"// before (hand-edited run metadata)\n{\"model_bindings\": {\"overrides\": {\"tiers\": {\"small\": \"haiku\"}}}}\n// after\n{\"model_bindings\": {\"overrides\": {\"nodes\": {\"review\": \"haiku\"}}}}","handlingStrategy":"validation","validationCode":"function isSafeRunBindings(meta: unknown): boolean {\n  const m = meta as { model_bindings?: { overrides?: Record<string, unknown>; effective?: unknown } } | null;\n  const o = m?.model_bindings?.overrides;\n  return !m?.model_bindings?.effective\n    && (!o || !('tiers' in o) && !('aliases' in o));\n}","typeGuard":"function hasValidBindings(m: unknown): m is { model_bindings?: { overrides?: Record<string, never> } } {\n  return typeof m === 'object' && m !== null && isSafeRunBindings(m);\n}","tryCatchPattern":"try {\n  const bindings = readRunModelBindingsMetadata(run);\n  startRun(run.id, bindings);\n} catch (err) {\n  if ((err as Error).message.includes('invalid model_bindings')) {\n    log.warn('Discarding corrupt run metadata; restarting run fresh', { runId: run.id });\n    startFreshRun(run.workflowId);\n  } else throw err;\n}","preventionTips":["Never hand-edit run rows' metadata columns; use CLI/config to change model settings.","Resume runs with the same binary version that created them.","Do not persist computed `effective` bindings into run metadata.","Keep schema-shape changes to run metadata behind additive, versioned writers."],"tags":["workflow","metadata","model-bindings","persistence"],"backgroundTag":"invalid-run-metadata","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}