ComposioHQ/composio · error · ValueError

Dynamic-key schema reference {reference!r} must be a local J

Error message

Dynamic-key schema reference {reference!r} must be a local JSON Pointer

What it means

schema_converter.py only supports local JSON Pointer references ("#" or "#/path/...") when resolving dynamic-key schemas. If a $ref is an external/absolute URL or a plain fragment without "#/", _resolve_local_json_pointer raises this ValueError during model construction because the converter has no mechanism to fetch external references.

Source

Thrown at python/composio/utils/schema_converter.py:344

    """Whether Pydantic must run after validation to materialize a default."""
    if isinstance(schema, list):
        return any(_contains_default(item) for item in schema)
    if not isinstance(schema, dict):
        return False
    return "default" in schema or any(
        _contains_default(value) for value in schema.values()
    )


def _resolve_local_json_pointer(
    reference: str,
    root_schema: t.Dict[str, t.Any],
) -> t.Any:
    """Resolve a local JSON Pointer or fail while the model is constructed."""
    if reference == "#":
        return root_schema
    if not reference.startswith("#/"):
        raise ValueError(
            f"Dynamic-key schema reference {reference!r} must be a local JSON Pointer"
        )

    current: t.Any = root_schema
    for raw_token in unquote(reference[2:]).split("/"):
        token = raw_token.replace("~1", "/").replace("~0", "~")
        if isinstance(current, dict) and token in current:
            current = current[token]
            continue
        if isinstance(current, list):
            try:
                current = current[int(token)]
                continue
            except (ValueError, IndexError):
                pass
        raise ValueError(f"Unresolvable dynamic-key schema reference: {reference!r}")
    return current

View on GitHub (pinned to 64b1b85502)

Solutions

  1. Inline the external schema at the referencing site, or convert the $ref into a local pointer ("#/definitions/X") by embedding the target under definitions/$defs in the same document
  2. Replace anchor refs with JSON Pointer refs like "#/definitions/anchor-name"
  3. If the schema is backend-generated, report it — external refs are not supported by the converter

Example fix

# before
{"$ref": "https://schemas.example.com/user.json"}
# after
{"$defs": {"user": {...}}, "$ref": "#/$defs/user"}
Defensive patterns

Strategy: validation

Validate before calling

def refs_are_local(schema):
    if isinstance(schema, dict):
        r = schema.get("$ref")
        if r is not None and not (r == "#" or r.startswith("#/")):
            return False
        return all(refs_are_local(v) for v in schema.values())
    if isinstance(schema, list):
        return all(refs_are_local(i) for i in schema)
    return True
assert refs_are_local(schema)

Try / catch

try:
    build_model(schema)
except ValueError as e:
    if "must be a local JSON Pointer" in str(e):
        schema = inline_external_refs(schema)

Prevention

When it happens

Trigger: A tool input schema contains "$ref": "https://example.com/schema.json" (external), "#/definitions" without the leading slash form, or an anchor-style ref like "#myAnchor". The converter hits it while building the dynamic-key policy for a dict whose keys map to schemas.

Common situations: Tool schemas imported from external OpenAPI documents that keep remote $refs; specs using JSON Schema 2019-09 $anchor style; specs authored with $id-based instead of pointer-based refs; converted OpenAPI whose "#/components/schemas/..." refs were mangled during transformation.

Related errors


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