mastra-ai/mastra · error

Mode "${mode.id}" transitionsTo references unknown mode "${m

Error message

Mode "${mode.id}" transitionsTo references unknown mode "${mode.transitionsTo}"

What it means

validateModes checks that every mode's transitionsTo target exists among the declared mode ids. If a mode references a mode id that was never registered, the controller would be unable to transition, so construction fails with this error naming both the referencing mode and the unknown target.

Source

Thrown at packages/core/src/agent-controller/agent-controller.ts:84

      throw new Error(`Duplicate mode id "${mode.id}" found when creating the AgentController`);
    }

    modeIds.add(mode.id);

    const modeRecord = mode as unknown as { id: string; tools?: unknown; additionalTools?: unknown };
    if (modeRecord.tools && modeRecord.additionalTools) {
      throw new Error(
        `Mode "${modeRecord.id}" cannot set both "tools" and "additionalTools" - choose replace OR augment`,
      );
    }
  }

  for (const mode of modes) {
    if (mode.transitionsTo === mode.id) {
      throw new Error(`Mode "${mode.id}" transitionsTo cannot reference itself`);
    }
    if (mode.transitionsTo && !modeIds.has(mode.transitionsTo)) {
      throw new Error(`Mode "${mode.id}" transitionsTo references unknown mode "${mode.transitionsTo}"`);
    }
  }
}

/**
 * Build a user-facing message for a non-success stream finish reason.
 *
 * Anthropic's classifier blocks / model refusals (e.g. `claude-fable-5`) surface
 * through the AI SDK as a `content-filter` finish reason, with details on
 * `providerMetadata.anthropic.stopDetails`. Without explicit handling these
 * runs end on an empty assistant message with no error, so the run appears to
 * silently stop. Returning a message here lets the controller finalize the run
 * into an explicit terminal error state.
 */
/**
 * The Anthropic model that `claude-fable-5` runs are automatically retried on
 * server-side when fable-5's safety classifiers block a turn. See
 * {@link buildFableFallbackProviderOptions}.

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Add the missing mode with the referenced id to the modes array
  2. Fix the transitionsTo value to match an existing mode id exactly (case-sensitive)
  3. Grep the config for all transitionsTo values and verify each exists in modes

Example fix

// before
modes: [{ id: 'plan', transitionsTo: 'execute' }]
// after
modes: [{ id: 'plan', transitionsTo: 'execute' }, { id: 'execute' }]
Defensive patterns

Strategy: validation

Validate before calling

function assertTransitionsResolve(modes: { id: string; transitionsTo?: string }[]): void {
  const ids = new Set(modes.map(m => m.id));
  for (const m of modes) {
    if (m.transitionsTo && !ids.has(m.transitionsTo))
      throw new Error(`Mode "${m.id}" references unknown mode "${m.transitionsTo}"`);
  }
}
assertTransitionsResolve(config.modes);

Try / catch

try {
  new AgentController(config);
} catch (e) {
  if ((e as Error).message.includes('references unknown mode')) {
    // add the missing mode or correct the transitionsTo id
  }
}

Prevention

When it happens

Trigger: new AgentController({ modes: [...] }) where mode 'plan' has transitionsTo: 'execute' but no mode with id 'execute' exists — due to typos, removed modes, or case-sensitive id mismatches.

Common situations: Deleting or renaming a mode without updating other modes' transitionsTo; typos in mode ids ('Execute' vs 'execute'); conditional config assembly that drops a mode other modes still reference.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/1668025b9ecb30d2. Report an issue: GitHub.