ComposioHQ/composio · error · ValidationError
Custom tool slug collision: "${finalSlug}" is already regist
Error message
Custom tool slug collision: "${finalSlug}" is already registered. What it means
While building the internal custom-tools map, Composio detected that two custom tools resolve to the same final slug (compared case-insensitively). The SDK registers every custom tool under its final slug and cannot disambiguate duplicates, so it throws a ValidationError during map construction rather than failing later at execution time.
Source
Thrown at ts/packages/core/src/models/CustomTool.ts:349
const byToolkitAndOriginalSlug = new Map<string, CustomToolsMapEntry>();
const ambiguousOriginalSlugs = new Set<string>();
const addEntry = (handle: CustomTool, finalSlug: string, toolkit?: string) => {
const originalSlug = handle.slug.toUpperCase();
// Custom tool slugs are matched case-insensitively across local and response maps.
const finalSlugKey = finalSlug.toUpperCase();
// Length validated early in createCustomTool/createCustomToolkit, but check as safety net
if (finalSlug.length > MAX_SLUG_LENGTH) {
throw new ValidationError(
`Custom tool slug "${handle.slug}" produces final slug "${finalSlug}" ` +
`which exceeds ${MAX_SLUG_LENGTH} characters.`
);
}
// Check cross-group collisions on final slug
if (byFinalSlug.has(finalSlugKey)) {
throw new ValidationError(
`Custom tool slug collision: "${finalSlug}" is already registered.`
);
}
const qualifiedKey = qualifiedOriginalSlugKey(toolkit, originalSlug);
if (byToolkitAndOriginalSlug.has(qualifiedKey)) {
throw new ValidationError(
`Custom tool slug collision: original slug "${handle.slug}" is already registered for toolkit "${toolkit ?? 'custom'}".`
);
}
const entry: CustomToolsMapEntry = { handle, finalSlug, toolkit };
byFinalSlug.set(finalSlugKey, entry);
byToolkitAndOriginalSlug.set(qualifiedKey, entry);
addOriginalSlugAlias({ byOriginalSlug, ambiguousOriginalSlugs, originalSlug, entry });
};
// Process standalone toolsView on GitHub (pinned to 64b1b85502)
Solutions
- Uniquely rename the colliding custom tool slug (check case-insensitive equality)
- List all registered custom tool slugs and diff them to find the duplicate pair
- If the duplicate comes from a custom toolkit, change the toolkit name or tool slug so the final slug differs
Example fix
// before
const tools = [defineTool({ slug: 'fetchPage' }), defineTool({ slug: 'fetch_page' })];
// after
const tools = [defineTool({ slug: 'fetchPage' }), defineTool({ slug: 'extractLinks' })]; Defensive patterns
Strategy: validation
Validate before calling
const final = (slug) => slug.toUpperCase(); // approximate SDK normalization
const seen = new Set<string>();
for (const t of customTools) {
const key = final(t.slug);
if (seen.has(key)) throw new Error(`Duplicate final slug: ${t.slug}`);
seen.add(key);
} Type guard
const isUniqueFinalSlugs = (tools: {slug: string}[]): boolean =>
new Set(tools.map(t => t.slug.toUpperCase())).size === tools.length; Try / catch
try { buildCustomToolsMap(tools); } catch (e) { if (e instanceof ValidationError && e.message.includes('slug collision')) { /* dedupe and retry */ } throw e; } Prevention
- Keep a single module exporting all custom tool slugs to review for collisions
- Treat slugs as case-insensitive unique identifiers in code review
- Add a startup assertion that all final slugs are unique
When it happens
Trigger: Registering two custom tools (via Composio custom tool definitions or custom toolkits) whose slugs collide after normalization — e.g. 'My_Tool' and 'my-tool', or a custom tool whose slug matches a toolkit-prefixed slug that reduces to the same final key. Surfaced from buildCustomToolsMap / buildCustomToolsMapFromResponse.
Common situations: Copying a custom tool definition and forgetting to change the slug; mixing SDK custom tools with tools loaded from a response that share names; case differences in slugs across environments; adding a tool to a toolkit that already exposes a similarly-named tool.
Related errors
- Custom tool slug collision: original slug "${handle.slug}" i
- Ambiguous custom tool slug "${slug}". Multiple custom toolki
- Custom tool slugs are not supported in preload.tools: ${cust
- Could not determine a home directory to store the Composio c
- Cache directory {directory} is not writable please provide a
AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28).
Data as JSON: /api/errors/ee5b10d4c5f299ba.
Report an issue: GitHub.