{"record":{"id":"e910830a69921e37","repo":"ComposioHQ/composio","slug":"tool-input-schema-property-names-produce-a-duplica","errorCode":null,"errorMessage":"Tool input schema property names produce a duplicate Python parameter alias {safe_name!r}","messagePattern":"Tool input schema property names produce a duplicate Python parameter alias (.+?)","errorType":"validation","errorClass":"InvalidSchemaError","httpStatus":null,"severity":"error","filePath":"python/composio/utils/shared.py","lineNumber":296,"sourceCode":"            on_unresolved=\"sentinel\",\n        ),\n    )\n    schema_params, aliases = _alias_schema_properties(aliased_schema)\n    return ToolSchemaAliases(schema=schema_params, aliases=aliases)\n\n\ndef _alias_schema_properties(schema: t.Dict[str, t.Any]) -> t.Tuple[dict, dict]:\n    properties = schema.get(\"properties\")\n    if not isinstance(properties, dict):\n        return schema, {}\n\n    aliases: t.Dict[str, t.Any] = {}\n    aliased_properties: t.Dict[str, t.Any] = {}\n\n    for original_name, property_schema in properties.items():\n        safe_name = _make_python_identifier(original_name)\n        if safe_name in aliased_properties:\n            raise InvalidSchemaError(\n                \"Tool input schema property names produce a duplicate Python \"\n                f\"parameter alias {safe_name!r}\"\n            )\n\n        nested_object_aliases: t.Dict[str, t.Any] = {}\n        nested_array_aliases: t.Dict[str, t.Any] = {}\n        if isinstance(property_schema, dict):\n            property_schema, nested_object_aliases = _alias_nested_object_schema(\n                property_schema\n            )\n            property_schema, nested_array_aliases = _alias_nested_array_schema(\n                property_schema\n            )\n\n        aliased_properties[safe_name] = property_schema\n        if safe_name != original_name or nested_object_aliases or nested_array_aliases:\n            aliases[safe_name] = original_name\n        if nested_object_aliases:","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/python/composio/utils/shared.py#L278-L314","documentation":"alias_tool_input_schema rewrites property names into valid Python identifiers; when two distinct original names collapse to the same safe alias (e.g. \"user-id\" and \"user_id\" both become user_id), the collision is rejected with InvalidSchemaError because the generated function signature would be ambiguous.","triggerScenarios":"A tool schema with properties like \"auth-token\" and \"auth_token\", or \"class\" and \"Class_\", or names differing only in punctuation/case that _make_python_identifier normalizes identically. Raised while building the aliased schema/signature, before any call happens.","commonSituations":"Backend tool definitions mixing naming conventions; recently added properties that collide with existing ones after normalization; specs generated from APIs with inconsistent param naming (kebab + snake variants of the same param).","solutions":["Rename one of the colliding properties in the tool schema so their sanitized forms differ (e.g. \"user-id\" → \"user_id_v2\")","Remove the redundant duplicate property if both spellings mean the same thing","If the schema is backend-managed, report the collision — it must be fixed at the source"],"exampleFix":"# before\n{\"properties\": {\"auth-token\": {...}, \"auth_token\": {...}}}\n# after\n{\"properties\": {\"auth_token\": {...}, \"auth_token_v2\": {...}}}","handlingStrategy":"validation","validationCode":"from composio.utils.shared import _make_python_identifier\ndef no_alias_collisions(schema):\n    props = schema.get(\"properties\", {})\n    seen = set()\n    for name in props:\n        alias = _make_python_identifier(name)\n        if alias in seen: return False\n        seen.add(alias)\n    return True","typeGuard":null,"tryCatchPattern":"try:\n    alias_tool_input_schema(schema)\nexcept InvalidSchemaError as e:\n    if \"duplicate Python parameter alias\" in str(e):\n        schema = rename_colliding_properties(schema)","preventionTips":["Use one naming convention across tool schema properties","Add a collision pre-check in schema CI when tools are defined in bulk","Report backend-defined collisions instead of patching locally"],"tags":["schema-alias","python-identifiers","tool-schema","naming-collision"],"backgroundTag":"duplicate-parameter-alias","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}