{"record":{"id":"8dfa00bec74c51c7","repo":"mastra-ai/mastra","slug":"duplicate-workspace-tool-name-exposedname-to","errorCode":null,"errorMessage":"Duplicate workspace tool name \"${exposedName}\": tool \"${name}\" conflicts with an already-registered tool. Check your tools config for duplicate \"name\" values.","messagePattern":"Duplicate workspace tool name \"(.+?)\": tool \"(.+?)\" conflicts with an already-registered tool\\. Check your tools config for duplicate \"name\" values\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/workspace/tools/tools.ts","lineNumber":466,"sourceCode":"              workspace: ctx?.workspace ?? workspace,\n            },\n            true,\n          ),\n      };\n    } else {\n      wrapped = { ...tool, requireApproval: config.requireApproval };\n    }\n\n    if (opts?.readTrackerMode) {\n      wrapped = wrapWithReadTracker(wrapped, workspace, readTracker, config, opts.readTrackerMode);\n    } else {\n      wrapped = wrapTool(wrapped, workspace, opts?.targets ?? {});\n    }\n\n    // Use custom name if provided, otherwise use the default constant name\n    const exposedName = config.name ?? name;\n    if (tools[exposedName]) {\n      throw new Error(\n        `Duplicate workspace tool name \"${exposedName}\": tool \"${name}\" conflicts with an already-registered tool. ` +\n          `Check your tools config for duplicate \"name\" values.`,\n      );\n    }\n    // When the tool is renamed, update its id to match so fallback-by-id\n    // resolution (in tool-call-step, llm-execution-step, etc.) won't allow\n    // the model to call the tool using the old default name.\n    if (exposedName !== name && 'id' in wrapped) {\n      wrapped = { ...wrapped, id: exposedName };\n    }\n\n    if (config.hooks) {\n      wrapped = wrapWithToolHooks(wrapped, config.hooks, exposedName, name);\n    }\n\n    // Write lock is outermost — serializes the entire enriched execute pipeline\n    if (opts?.useWriteLock) {\n      wrapped = wrapWithWriteLock(wrapped, writeLock);","sourceCodeStart":448,"sourceCodeEnd":484,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/workspace/tools/tools.ts#L448-L484","documentation":"Workspace tool registration keys tools by their exposed name (`config.name ?? defaultName`). If two tool configs resolve to the same exposed name, `addTool` throws a duplicate-name Error so registration fails fast rather than silently overwriting a tool. The error names both the internal tool and the colliding exposed name.","triggerScenarios":"Providing the same custom `name` for two different tool configs, or enabling the same built-in workspace tool twice (e.g. two read-file entries) so both map to one constant default name.","commonSituations":"Copy-pasting a tool config entry and forgetting to change `name`; spreading arrays of tool configs that both contain a renamed tool with the same name; dynamic config generation producing duplicate names.","solutions":["Give each conflicting tool config a unique `name`","Remove the duplicate config entry if it was added by mistake","If two instances of the same built-in tool are needed with different settings, expose them under distinct names"],"exampleFix":"// before\n{ tool: 'read-file', name: 'read' },\n{ tool: 'read-many-files', name: 'read' } // duplicate\n\n// after\n{ tool: 'read-file', name: 'read' },\n{ tool: 'read-many-files', name: 'read-many' }","handlingStrategy":"validation","validationCode":"const names = toolConfigs.map(c => c.name ?? defaultNameFor(c.tool));\nconst dupes = names.filter((n, i) => names.indexOf(n) !== i);\nif (dupes.length) throw new Error(`Duplicate workspace tool names: ${[...new Set(dupes)].join(', ')}`);","typeGuard":null,"tryCatchPattern":"try {\n  const tools = createWorkspaceToolConfigs(configs);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Duplicate workspace tool name')) {\n    console.error(err.message); // fix config names\n    throw err;\n  }\n  throw err;\n}","preventionTips":["Uniquely name every custom tool config; keep names in one constants file to spot collisions","Avoid enabling the same built-in tool twice without renaming one","Add a config-lint test that builds the tools map and asserts no duplicate keys"],"tags":["duplicate-name","configuration","tool-registration","workspace"],"backgroundTag":"duplicate-identifier","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}