{"record":{"id":"f3051a23a90f92f5","repo":"ComposioHQ/composio","slug":"context-slug-must-not-start-with-local-thi","errorCode":null,"errorMessage":"{context}: slug must not start with \"LOCAL_\" — this prefix is reserved for internal routing.","messagePattern":"(.+?): slug must not start with \"LOCAL_\" — this prefix is reserved for internal routing\\.","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"python/composio/core/models/custom_tool.py","lineNumber":94,"sourceCode":"# ────────────────────────────────────────────────────────────────\n# Slug validation helpers\n# ────────────────────────────────────────────────────────────────\n\n\ndef _validate_slug(slug: str, context: str) -> str:\n    \"\"\"Validate a custom tool or toolkit slug.\"\"\"\n    if not slug:\n        raise ValidationError(f\"{context}: slug is required\")\n\n    if not SLUG_REGEX.match(slug):\n        raise ValidationError(\n            f\"{context}: slug must only contain alphanumeric characters, \"\n            f\"underscores, and hyphens\"\n        )\n\n    upper = slug.upper()\n    if upper.startswith(\"LOCAL_\"):\n        raise ValidationError(\n            f'{context}: slug must not start with \"LOCAL_\" — '\n            f\"this prefix is reserved for internal routing.\"\n        )\n    if upper.startswith(\"COMPOSIO_\"):\n        raise ValidationError(\n            f'{context}: slug must not start with \"COMPOSIO_\" — '\n            f\"this prefix is reserved for Composio meta tools.\"\n        )\n\n    return slug\n\n\ndef _compute_final_slug_length(tool_slug: str, toolkit_slug: t.Optional[str]) -> int:\n    \"\"\"Compute the final slug length: LOCAL_[TOOLKIT_]SLUG.\"\"\"\n    length = len(LOCAL_TOOL_PREFIX) + len(tool_slug)\n    if toolkit_slug:\n        length += len(toolkit_slug) + 1  # +1 for underscore separator\n    return length","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/python/composio/core/models/custom_tool.py#L76-L112","documentation":"Raised when a custom tool or toolkit slug starts with LOCAL_ (case-insensitive). Composio prefixes internally-routed local tools with LOCAL_, so user slugs in that namespace would collide with the routing layer.","triggerScenarios":"Naming a custom tool slug like 'local_search' or 'LOCAL_TOOL_X' via Tool(...) or a toolkit with slug starting with 'local_'.","commonSituations":"Developers prefixing their own tools with local_ thinking it groups them; copying internal Composio examples; naming tools for local-file operations like local_fs_read.","solutions":["Rename the slug to drop the LOCAL_ prefix, e.g. 'local_search' -> 'search' or 'mylocal_search'","Use your own namespace prefix like 'acme_' or 'team_' for grouping"],"exampleFix":"# before\nTool(slug=\"local_file_reader\", ...)\n\n# after\nTool(slug=\"file_reader\", ...)  # or \"my_file_reader\"","handlingStrategy":"validation","validationCode":"def ensure_prefix(slug: str) -> str:\n    if slug.upper().startswith((\"LOCAL_\", \"COMPOSIO_\")):\n        return \"usr_\" + slug\n    return slug","typeGuard":"def has_reserved_prefix(slug: str) -> bool:\n    return slug.upper().startswith((\"LOCAL_\", \"COMPOSIO_\"))","tryCatchPattern":"try:\n    Tool(slug=slug, ...)\nexcept ValidationError:\n    Tool(slug=\"app_\" + slug, ...)","preventionTips":["Avoid LOCAL_ and COMPOSIO_ prefixes in user-defined slugs","Use a project-specific prefix like myteam_ for namespacing","Check the reserved-prefix list in the custom_tool docs before naming"],"tags":["python","custom-tools","reserved-prefix"],"backgroundTag":"reserved-identifier-conflict","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}