PrefectHQ/fastmcp · error · ValueError
External or non-local reference not supported: {ref_str}
Error message
External or non-local reference not supported: {ref_str} What it means
OpenAPIParser._resolve_ref only supports local JSON-pointer references that begin with '#/' (references within the same document). When a component's $ref points anywhere else — another file, an absolute URL, or any non-local string — the parser raises ValueError because cross-document resolution is not implemented. If the ref is not a string at all, the item is returned unresolved instead (no error).
Source
Thrown at fastmcp_slim/fastmcp/utilities/openapi/parser.py:169
"query": "query",
"header": "header",
"cookie": "cookie",
}
if location := locations.get(param_in):
return location
logger.warning(f"Unknown parameter location: {param_in}, defaulting to 'query'")
return "query"
def _resolve_ref(self, item: Any) -> Any:
"""Resolves a reference to its target definition."""
if isinstance(item, self.reference_cls):
ref_str = item.ref
# Ensure ref_str is a string before calling startswith()
if not isinstance(ref_str, str):
return item
try:
if not ref_str.startswith("#/"):
raise ValueError(
f"External or non-local reference not supported: {ref_str}"
)
parts = ref_str.strip("#/").split("/")
target = self.openapi
for part in parts:
if part.isdigit() and isinstance(target, list):
target = target[int(part)]
elif isinstance(target, BaseModel):
# Check class fields first, then model_extra
if part in target.__class__.model_fields:
target = getattr(target, part, None)
elif target.model_extra and part in target.model_extra:
target = target.model_extra[part]
else:
# Special handling for components
if part == "components" and hasattr(target, "components"):View on GitHub (pinned to 1f02114297)
Solutions
- Bundle the spec into a single self-contained document before parsing: `npx @redocly/cli bundle spec.yaml -o bundled.json` (or swagger-cli bundle) so all refs become '#/components/...'.
- Inline external schemas manually: copy the referenced definitions into components/schemas and rewrite the $ref to '#/components/schemas/Name'.
- If the external ref points to a stable URL, pre-fetch it and merge it into your spec at load time with a small script before calling the parser.
- Regenerate the spec from the source (e.g. FastAPI) ensuring a single-file export without external refs.
Example fix
// before (in spec.yaml) $ref: 'https://api.example.com/schemas/User.json' // after $ref: '#/components/schemas/User' # definition inlined into the same document
Defensive patterns
Strategy: validation
Validate before calling
import json
def find_external_refs(node, out=None):
out = [] if out is None else out
if isinstance(node, dict):
ref = node.get("$ref")
if isinstance(ref, str) and not ref.startswith("#/"):
out.append(ref)
for v in node.values():
find_external_refs(v, out)
elif isinstance(node, list):
for v in node:
find_external_refs(v, out)
return out
external = find_external_refs(spec)
assert not external, f"Bundle first, external refs: {external}" Type guard
def is_local_ref(ref: object) -> bool:
return isinstance(ref, str) and ref.startswith("#/") Try / catch
try:
routes = parse_openapi_to_http_routes(spec)
except ValueError as e:
if "External or non-local reference" in str(e):
raise SystemExit("Bundle the spec (e.g. redocly bundle) and retry") from e
raise Prevention
- Always bundle multi-file specs before shipping them to parsers.
- Run a ref scan (all $ref start with '#/') as a CI check.
- Avoid tools that emit URL or file-relative refs in exports.
- Keep a single self-contained spec artifact as the source of truth.
When it happens
Trigger: Parsing a spec whose schemas/parameters/responses contain $ref values like 'https://api.example.com/schemas/User.json', 'common.yaml#/components/schemas/X', or './types.json#/Foo' while running _extract_schema_as_dict, _extract_parameters, _extract_request_body, _extract_responses, or parse.
Common situations: Specs split across multiple files by a bundler that wasn't run (source refs left in); vendor-published specs referencing external schema URLs; manually edited specs with copied external refs; codegen output using relative file refs.
Related errors
- Cannot traverse part '{part}' in reference '{ref_str}'
- Reference part '{part}' not found in path '{ref_str}'
- AudioContent is not supported by the Anthropic API
- HTTP error {response.status_code}: {response.reason_phrase}
- HTTP request timed out ({type(exc).__name__})
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/7981aa99b1c97c33.
Report an issue: GitHub.