PrefectHQ/fastmcp · error · ValueError

External or non-local reference not supported: {ref_path}. F

Error message

External or non-local reference not supported: {ref_path}. FastMCP only supports local schema references starting with '#/'. Please include all schema definitions within the OpenAPI document.

What it means

FastMCP's `_replace_ref_with_defs` only rewrites local component-schema refs (`#/components/schemas/...`) into JSON-Schema `$defs` refs; any `$ref` that does not start with `#/` (i.e. an external file/URL or non-local document pointer) is unsupported and raises this ValueError. The library requires all schema definitions to be inlined in the OpenAPI document it parses.

Source

Thrown at fastmcp_slim/fastmcp/utilities/openapi/schemas.py:105

    - {"anyOf": [{"$ref": "#/components/schemas/..."}]}
    - {"allOf": [{"$ref": "#/components/schemas/..."}]}
    - {"oneOf": [{"$ref": "#/components/schemas/..."}]}

    Args:
        info: dict[str, Any]
        description: str | None

    Returns:
        dict[str, Any]
    """
    schema = info.copy()
    if ref_path := schema.get("$ref"):
        if isinstance(ref_path, str):
            if ref_path.startswith("#/components/schemas/"):
                schema_name = ref_path.split("/")[-1]
                schema["$ref"] = f"#/$defs/{schema_name}"
            elif not ref_path.startswith("#/"):
                raise ValueError(
                    f"External or non-local reference not supported: {ref_path}. "
                    f"FastMCP only supports local schema references starting with '#/'. "
                    f"Please include all schema definitions within the OpenAPI document."
                )
    elif properties := schema.get("properties"):
        if "$ref" in properties:
            schema["properties"] = _replace_ref_with_defs(properties)
        else:
            schema["properties"] = {
                prop_name: _replace_ref_with_defs(prop_schema)
                for prop_name, prop_schema in properties.items()
            }
    elif item_schema := schema.get("items"):
        schema["items"] = _replace_ref_with_defs(item_schema)
    for section in ["anyOf", "allOf", "oneOf"]:
        if section in schema:
            schema[section] = [_replace_ref_with_defs(item) for item in schema[section]]
    if additionalProperties := schema.get("additionalProperties"):

View on GitHub (pinned to 1f02114297)

Solutions

  1. Bundle the spec into a single self-contained document before parsing (e.g. `npx @redocly/cli bundle openapi.yaml -o bundled.yaml` or swagger-cli bundle).
  2. Replace external refs manually by copying the referenced definitions into `components/schemas` of the same document and using `#/components/schemas/...` refs.
  3. If the tool producing the spec supports an 'inline' or 'dereference' option, enable it so all refs are local.

Example fix

// before
"$ref": "./pet.yaml#/components/schemas/Pet"
// after (bundled, local)
"$ref": "#/components/schemas/Pet"
Defensive patterns

Strategy: validation

Validate before calling

import re
_EXTERNAL_REF = re.compile(r'^\$ref":\s*"(?!#/)', re.M)

def has_external_refs(spec_text: str) -> bool:
    return bool(_EXTERNAL_REF.search(spec_text))

Type guard

def is_local_ref(ref: object) -> bool:
    return isinstance(ref, str) and ref.startswith("#/")

Try / catch

try:
    tools = await client.get_tools_from_openapi(spec)
except ValueError as e:
    if "External or non-local reference" in str(e):
        spec = bundle_spec(spec)  # e.g. redocly bundle
        tools = await client.get_tools_from_openapi(spec)
    else:
        raise

Prevention

When it happens

Trigger: Parsing an OpenAPI document whose schemas contain refs like `pet.yaml#/Pet`, `https://example.com/schemas/pet.json`, or `definitions.json#/Pet` — anything not beginning with `#/`.

Common situations: Modular/multi-file API specs assembled from multiple YAML files with file-relative refs, specs that reference schemas hosted on external URLs, or vendor docs split across documents. Very common with specs produced by design-first tools that support external refs (Swagger, Stoplight) before bundling.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/ec0169a146558bf2. Report an issue: GitHub.