mastra-ai/mastra · error

Mode ${mode.id} requires a defaultModelId when no backing ag

Error message

Mode ${mode.id} requires a defaultModelId when no backing agent is configured

What it means

When the controller has no backing agent in config, it constructs a per-mode agent on demand; that requires the mode to declare a defaultModelId so the agent has a model. A mode without defaultModelId and without a backing agent is an invalid configuration, so construction fails fast.

Source

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

    if (mode.agent) {
      if (!this.#legacyAgentMode[mode.id]) {
        this.#legacyAgentMode[mode.id] = mode.agent;
      }
      return this.#legacyAgentMode[mode.id]!;
    }

    // Shared backing agent — reuse the single instance.
    // The harness never mutates the agent's own instructions or tools.
    // Mode instructions are passed at call time via buildAgentMessageStreamOptions;
    // mode tools are resolved at execution time via buildToolsets.
    if (this.config.agent) {
      return this.config.agent;
    }

    // No backing agent — construct one per mode (cached).
    if (!this.#legacyAgentMode[mode.id]) {
      if (!mode.defaultModelId) {
        throw new Error(`Mode ${mode.id} requires a defaultModelId when no backing agent is configured`);
      }

      const instructions = [this.#instructions ?? '', mode.instructions].filter(Boolean).join('\n');
      const modeTools = {
        ...mode.tools,
        ...mode.additionalTools,
      };

      // Model resolution flows through the gateways registered on the internal
      // Mastra instance: the bare model id string is handed to the Agent, and
      // `propagateRuntimeServicesToAgent` attaches the internal Mastra so the
      // model router resolves it via the configured gateways (auth included).
      const model = mode.defaultModelId;
      this.#legacyAgentMode[mode.id] = new Agent({
        id: `${this.id}-agent`,
        name: `Harness ${this.id} agent`,
        model,
        instructions,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Set defaultModelId on the mode definition (use a literal model name/id, e.g. 'openai/gpt-4o')
  2. Or provide config.agent so the mode does not need to construct its own agent
  3. Validate mode configs at startup to catch missing defaultModelId before a request triggers it

Example fix

// before
const mode = { id: 'research', instructions: '...' };
// after
const mode = { id: 'research', instructions: '...', defaultModelId: 'openai/gpt-4o' };
Defensive patterns

Strategy: validation

Validate before calling

if (!controller.config.agent && !mode.defaultModelId) {
  throw new Error(`Mode ${mode.id} is misconfigured: needs defaultModelId or a backing agent`);
}

Type guard

function isRunnableMode(mode): mode is typeof mode & { defaultModelId: string } {
  return typeof mode.defaultModelId === 'string' && mode.defaultModelId.length > 0;
}

Prevention

When it happens

Trigger: Calling getAgentForMode (directly or via stream/generate paths) with a mode that has no config.agent and no mode.defaultModelId set.

Common situations: Registering a custom mode object and forgetting defaultModelId; refactoring from a backed-agent setup to mode-based setup; copying mode definitions across projects where the agent was previously supplied.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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