{"record":{"id":"0622bcee789e5fc6","repo":"mastra-ai/mastra","slug":"mode-moderecord-id-cannot-set-both-tools-an","errorCode":null,"errorMessage":"Mode \"${modeRecord.id}\" cannot set both \"tools\" and \"additionalTools\" - choose replace OR augment","messagePattern":"Mode \"(.+?)\" cannot set both \"tools\" and \"additionalTools\" - choose replace OR augment","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/agent-controller/agent-controller.ts","lineNumber":73,"sourceCode":" * (e.g. `(\"a\\0b\", \"c\")` vs `(\"a\", \"b\\0c\")`).\n */\nfunction sessionRegistryKey(resourceId: string, scope?: string): string {\n  return JSON.stringify([resourceId, scope ?? null]);\n}\n\nfunction validateModes(modes: AgentControllerMode[]): void {\n  const modeIds = new Set<string>();\n\n  for (const mode of modes) {\n    if (modeIds.has(mode.id)) {\n      throw new Error(`Duplicate mode id \"${mode.id}\" found when creating the AgentController`);\n    }\n\n    modeIds.add(mode.id);\n\n    const modeRecord = mode as unknown as { id: string; tools?: unknown; additionalTools?: unknown };\n    if (modeRecord.tools && modeRecord.additionalTools) {\n      throw new Error(\n        `Mode \"${modeRecord.id}\" cannot set both \"tools\" and \"additionalTools\" - choose replace OR augment`,\n      );\n    }\n  }\n\n  for (const mode of modes) {\n    if (mode.transitionsTo === mode.id) {\n      throw new Error(`Mode \"${mode.id}\" transitionsTo cannot reference itself`);\n    }\n    if (mode.transitionsTo && !modeIds.has(mode.transitionsTo)) {\n      throw new Error(`Mode \"${mode.id}\" transitionsTo references unknown mode \"${mode.transitionsTo}\"`);\n    }\n  }\n}\n\n/**\n * Build a user-facing message for a non-success stream finish reason.\n *","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/agent-controller/agent-controller.ts#L55-L91","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Remove one of the two properties — move the base tools into additionalTools if you want augmentation","Split into two modes if you genuinely need both replace and augment behavior","Ensure config-merge logic does not combine tools and additionalTools into one mode"],"exampleFix":"// before\n{ id: 'chat', tools: { read: readTool }, additionalTools: { write: writeTool } }\n// after\n{ id: 'chat', additionalTools: { read: readTool, write: writeTool } }","handlingStrategy":"validation","validationCode":"function assertNotBothTools(modes: { id: string; tools?: unknown; additionalTools?: unknown }[]): void {\n  for (const m of modes) {\n    if (m.tools && m.additionalTools) throw new Error(`Mode \"${m.id}\" sets both tools and additionalTools`);\n  }\n}\nassertNotBothTools(config.modes);","typeGuard":null,"tryCatchPattern":"try {\n  new AgentController(config);\n} catch (e) {\n  if ((e as Error).message.includes('both \"tools\" and \"additionalTools\"')) {\n    // merge the offending mode's tools into additionalTools and retry\n  }\n}","preventionTips":["Pick one tool-configuration style per mode (replace OR augment)","Ensure config-merge helpers don't combine both fields","Document the mutually-exclusive constraint in mode templates"],"tags":["configuration","agent-controller","tools","mutually-exclusive"],"backgroundTag":"mutually-exclusive-config-options","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}