{"record":{"id":"26feb9f3aa201fc5","repo":"mastra-ai/mastra","slug":"duplicate-mode-id-mode-id-found-when-creating","errorCode":null,"errorMessage":"Duplicate mode id \"${mode.id}\" found when creating the AgentController","messagePattern":"Duplicate mode id \"(.+?)\" found when creating the AgentController","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/agent-controller/agent-controller.ts","lineNumber":66,"sourceCode":"  ToolCategory,\n} from './types';\n\n/**\n * Registry key for the session map. JSON-encodes the (resourceId, scope) pair\n * so the key is collision-proof for arbitrary strings: a scoped session can\n * never collide with an unscoped one or with a different resource/scope split\n * (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}\"`);","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/agent-controller/agent-controller.ts#L48-L84","documentation":"validateModes runs when constructing an AgentController and enforces that every agent mode has a unique id. If two modes share the same id, it throws immediately at construction time so duplicate mode registrations fail fast rather than causing ambiguous mode resolution at runtime.","triggerScenarios":"Passing a modes array to new AgentController(config) containing two AgentControllerMode objects with identical id values, e.g. copy-pasted mode definitions or merging mode lists from two sources without deduplication.","commonSituations":"Copy-pasting a mode config and forgetting to change its id; programmatically merging default and user modes that both define an 'edit' or 'ask' id; feature flags that append the same mode twice.","solutions":["Give each mode in the modes array a unique id before constructing the controller","Deduplicate merged mode lists (e.g. by id) prior to construction","Check for double registration of the same mode from config files or plugins"],"exampleFix":"// before\nmodes: [{ id: 'chat', ... }, { id: 'chat', ... }]\n// after\nmodes: [{ id: 'chat', ... }, { id: 'review', ... }]","handlingStrategy":"validation","validationCode":"function assertUniqueModeIds(modes: { id: string }[]): void {\n  const ids = modes.map(m => m.id);\n  if (new Set(ids).size !== ids.length) throw new Error('Duplicate mode ids: ' + ids.join(','));\n}\nassertUniqueModeIds(config.modes);","typeGuard":null,"tryCatchPattern":"try {\n  const controller = new AgentController(config);\n} catch (e) {\n  if ((e as Error).message.startsWith('Duplicate mode id')) {\n    // dedupe config.modes by id and reconstruct\n  }\n}","preventionTips":["Deduplicate mode arrays by id before constructing","Never append the same mode object twice when merging configs","Use constants for mode ids to avoid copy-paste drift"],"tags":["configuration","agent-controller","duplicate-id","startup"],"backgroundTag":"duplicate-identifier-configuration","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}