coleam00/Archon · error · Error

Workflow run has invalid model_bindings metadata.

Error message

Workflow run has invalid model_bindings metadata.

What it means

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.

Source

Thrown at packages/workflows/src/model-validation.ts:512

  const value = metadata?.[RUN_MODEL_BINDINGS_METADATA_KEY];
  if (value === undefined) return undefined;
  const parsed = runModelBindingsMetadataSchema.safeParse(value);
  if (!parsed.success) {
    const path = parsed.error.issues[0]?.path ?? [];
    const bindingName = typeof path[2] === 'string' ? path[2] : 'unknown';
    if (path.includes('thinking')) {
      throw new Error(`Model binding '${bindingName}' has invalid thinking options.`);
    }
    if (path.includes('effort')) {
      throw new Error(`Model binding '${bindingName}' has an invalid effort.`);
    }
    if (path[0] === 'overrides' && (path[1] === 'tiers' || path[1] === 'aliases')) {
      throw new Error(`Workflow run has invalid model_bindings ${path[1]} metadata.`);
    }
    if (path[0] === 'effective') {
      throw new Error('Workflow run has invalid effective model bindings.');
    }
    throw new Error('Workflow run has invalid model_bindings metadata.');
  }

  const tiers = Object.fromEntries(
    Object.entries(parsed.data.overrides.tiers ?? {}).map(([name, preset]) => [
      name,
      normalizePersistedOverridePreset(name, preset),
    ])
  );
  const aliases = Object.fromEntries(
    Object.entries(parsed.data.overrides.aliases ?? {}).map(([name, preset]) => [
      name,
      normalizePersistedOverridePreset(name, preset),
    ])
  );
  for (const [name, preset] of Object.entries(parsed.data.effective.aliases)) {
    assertValidPersistedPreset(name, preset);
  }

View on GitHub (pinned to 0773b97458)

Solutions

  1. 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.
  2. Check which binary version wrote the run; resume with the same version that created it.
  3. Set model tiers/aliases through supported config (.archon/config.yaml tiers.*, `archon ai tier set`) instead of injecting run metadata.
  4. If the run row is unrecoverable, start a fresh run; the workflow definition remains the source of truth.

Example fix

// before (hand-edited run metadata)
{"model_bindings": {"overrides": {"tiers": {"small": "haiku"}}}}
// after
{"model_bindings": {"overrides": {"nodes": {"review": "haiku"}}}}
Defensive patterns

Strategy: validation

Validate before calling

function isSafeRunBindings(meta: unknown): boolean {
  const m = meta as { model_bindings?: { overrides?: Record<string, unknown>; effective?: unknown } } | null;
  const o = m?.model_bindings?.overrides;
  return !m?.model_bindings?.effective
    && (!o || !('tiers' in o) && !('aliases' in o));
}

Type guard

function hasValidBindings(m: unknown): m is { model_bindings?: { overrides?: Record<string, never> } } {
  return typeof m === 'object' && m !== null && isSafeRunBindings(m);
}

Try / catch

try {
  const bindings = readRunModelBindingsMetadata(run);
  startRun(run.id, bindings);
} catch (err) {
  if ((err as Error).message.includes('invalid model_bindings')) {
    log.warn('Discarding corrupt run metadata; restarting run fresh', { runId: run.id });
    startFreshRun(run.workflowId);
  } else throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01). Data as JSON: /api/errors/94bf0b5bae1b8a40. Report an issue: GitHub.