PrefectHQ/fastmcp · error · ValueError

Cannot traverse part '{part}' in reference '{ref_str}'

Error message

Cannot traverse part '{part}' in reference '{ref_str}'

What it means

While walking a local '#/...' JSON pointer, _resolve_ref reached a node that is neither a pydantic model nor a dict, so there is no way to look up the next path segment — e.g. the pointer descended into a scalar (string/int) or a list and then tried to index by name. The parser raises ValueError naming the offending part and full ref string. It almost always indicates a malformed $ref that doesn't match the actual document structure.

Source

Thrown at fastmcp_slim/fastmcp/utilities/openapi/parser.py:196

                        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"):
                                target = target.components
                            elif hasattr(target, part):  # Fallback check
                                target = getattr(target, part, None)
                            else:
                                target = None  # Part not found
                    elif isinstance(target, dict):
                        target = target.get(part)
                    else:
                        raise ValueError(
                            f"Cannot traverse part '{part}' in reference '{ref_str}'"
                        )

                    if target is None:
                        raise ValueError(
                            f"Reference part '{part}' not found in path '{ref_str}'"
                        )

                # Handle nested references
                if isinstance(target, self.reference_cls):
                    return self._resolve_ref(target)

                return target
            except (AttributeError, KeyError, IndexError, TypeError, ValueError) as e:
                raise ValueError(f"Failed to resolve reference '{ref_str}': {e}") from e

        return item

View on GitHub (pinned to 1f02114297)

Solutions

  1. Print the target document at that pointer and compare each segment against the real structure; fix the $ref path so every segment resolves to a dict/model.
  2. Remember JSON pointers escape '/' in key names as '~1' and '~' as '~0' — escape keys containing slashes in schemas (e.g. 'paths/x~1users').
  3. If the target is an array, use its numeric index in the pointer instead of a name (or restructure the spec into a keyed object).
  4. Regenerate the spec from source so refs are produced by the framework instead of hand-maintained.
  5. Validate the document with openapi-spec-validator, which catches malformed $ref pointers before parsing.

Example fix

// before
$ref: '#/components/responses/400/content/application~1json/schema'

// after  (verify segment-by-segment; '400' must actually be a key there)
$ref: '#/components/responses/BadRequest/content/application~1json/schema'
Defensive patterns

Strategy: validation

Validate before calling

import json

def check_ref_pointer(spec: dict, ref: str) -> bool:
    if not ref.startswith("#/"):
        return False
    target = spec
    for part in ref[2:].split("/"):
        part = part.replace("~1", "/").replace("~0", "~")
        if not isinstance(target, dict) or part not in target:
            return False
        target = target[part]
    return True

refs = [r for r in walk_refs(spec)]
bad = [r for r in refs if not check_ref_pointer(spec, r)]
assert not bad, f"Pointers don't match document structure: {bad}"

Type guard

def resolvable_pointer(doc: dict, ref: str) -> bool:
    if not (isinstance(ref, str) and ref.startswith("#/")):
        return False
    node = doc
    for part in ref[2:].split("/"):
        if not isinstance(node, dict) or part not in node:
            return False
        node = node[part]
    return True

Try / catch

try:
    routes = parse_openapi_to_http_routes(spec)
except ValueError as e:
    if "Cannot traverse part" in str(e):
        logger.error("Malformed $ref pointer: %s", e)
        raise SystemExit("Fix the ref path to match the document nesting") from e
    raise

Prevention

When it happens

Trigger: A $ref like '#/components/schemas/User/properties/name' where an intermediate segment names a scalar or array (e.g. 'schemas' is a list, or 'User' resolved to a string); pointer segments that don't correspond to the document's nesting because the ref was hand-edited or generated against a different spec.

Common situations: Refs written for a different spec version/layout than the one being parsed; JSON-pointer syntax mistakes (using '.' instead of '/', forgetting that array elements need numeric indices); automated ref rewriting tools producing paths into the wrong subtree.

Related errors


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