mastra-ai/mastra · error

Mode "${modeRecord.id}" cannot set both "tools" and "additio

Error message

Mode "${modeRecord.id}" cannot set both "tools" and "additionalTools" - choose replace OR augment

What it means

A mode may either replace the controller's tool set (tools) or augment it (additionalTools), but not both — the semantics would be ambiguous. validateModes throws at AgentController construction when a single mode sets both properties, forcing an explicit choose-one configuration.

Source

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

 * (e.g. `("a\0b", "c")` vs `("a", "b\0c")`).
 */
function sessionRegistryKey(resourceId: string, scope?: string): string {
  return JSON.stringify([resourceId, scope ?? null]);
}

function validateModes(modes: AgentControllerMode[]): void {
  const modeIds = new Set<string>();

  for (const mode of modes) {
    if (modeIds.has(mode.id)) {
      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.
 *

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Remove one of the two properties — move the base tools into additionalTools if you want augmentation
  2. Split into two modes if you genuinely need both replace and augment behavior
  3. Ensure config-merge logic does not combine tools and additionalTools into one mode

Example fix

// before
{ id: 'chat', tools: { read: readTool }, additionalTools: { write: writeTool } }
// after
{ id: 'chat', additionalTools: { read: readTool, write: writeTool } }
Defensive patterns

Strategy: validation

Validate before calling

function assertNotBothTools(modes: { id: string; tools?: unknown; additionalTools?: unknown }[]): void {
  for (const m of modes) {
    if (m.tools && m.additionalTools) throw new Error(`Mode "${m.id}" sets both tools and additionalTools`);
  }
}
assertNotBothTools(config.modes);

Try / catch

try {
  new AgentController(config);
} catch (e) {
  if ((e as Error).message.includes('both "tools" and "additionalTools"')) {
    // merge the offending mode's tools into additionalTools and retry
  }
}

Prevention

When it happens

Trigger: Defining an AgentControllerMode with both a non-empty tools object and a non-empty additionalTools object; typically from merging two partial mode configs (one specifying tools, the other additionalTools) into the same mode.

Common situations: Combining a base-mode template (with tools) with a per-deployment override (with additionalTools); copy-paste edits adding extra tools without realizing tools was already set; framework defaults that pre-populate tools.

Related errors


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