ComposioHQ/composio · error · InvalidSchemaError

Tool input schema property names produce a duplicate Python…

Error message

Tool input schema property names produce a duplicate Python parameter alias {safe_name!r}

What it means

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.

Solutions

  1. Rename one of the colliding properties in the tool schema so their sanitized forms differ (e.g. "user-id" → "user_id_v2")
  2. Remove the redundant duplicate property if both spellings mean the same thing
  3. If the schema is backend-managed, report the collision — it must be fixed at the source

Example fix

# before
{"properties": {"auth-token": {...}, "auth_token": {...}}}
# after
{"properties": {"auth_token": {...}, "auth_token_v2": {...}}}
Defensive patterns

Strategy: validation

Validate before calling

from composio.utils.shared import _make_python_identifier
def no_alias_collisions(schema):
    props = schema.get("properties", {})
    seen = set()
    for name in props:
        alias = _make_python_identifier(name)
        if alias in seen: return False
        seen.add(alias)
    return True

Try / catch

try:
    alias_tool_input_schema(schema)
except InvalidSchemaError as e:
    if "duplicate Python parameter alias" in str(e):
        schema = rename_colliding_properties(schema)

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Related errors


AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28). Data as JSON: /api/errors/e910830a69921e37. Report an issue: GitHub.

Appendix: source

Thrown at python/composio/utils/shared.py:296

            on_unresolved="sentinel",
        ),
    )
    schema_params, aliases = _alias_schema_properties(aliased_schema)
    return ToolSchemaAliases(schema=schema_params, aliases=aliases)


def _alias_schema_properties(schema: t.Dict[str, t.Any]) -> t.Tuple[dict, dict]:
    properties = schema.get("properties")
    if not isinstance(properties, dict):
        return schema, {}

    aliases: t.Dict[str, t.Any] = {}
    aliased_properties: t.Dict[str, t.Any] = {}

    for original_name, property_schema in properties.items():
        safe_name = _make_python_identifier(original_name)
        if safe_name in aliased_properties:
            raise InvalidSchemaError(
                "Tool input schema property names produce a duplicate Python "
                f"parameter alias {safe_name!r}"
            )

        nested_object_aliases: t.Dict[str, t.Any] = {}
        nested_array_aliases: t.Dict[str, t.Any] = {}
        if isinstance(property_schema, dict):
            property_schema, nested_object_aliases = _alias_nested_object_schema(
                property_schema
            )
            property_schema, nested_array_aliases = _alias_nested_array_schema(
                property_schema
            )

        aliased_properties[safe_name] = property_schema
        if safe_name != original_name or nested_object_aliases or nested_array_aliases:
            aliases[safe_name] = original_name
        if nested_object_aliases:

View on GitHub (pinned to 64b1b85502)