BerriAI/litellm · error · ValueError

Path parameter '{param_name}' must not contain path separato

Error message

Path parameter '{param_name}' must not contain path separators

What it means

Security guard in litellm's OpenAPI-to-MCP tool generator. When a generated MCP tool substitutes a caller-supplied value into a URL path segment, _sanitize_path_parameter_value rejects any value containing / (backslashes are normalized to / first) with this ValueError, blocking path traversal and URL-segment injection. On the generated tool's REST execution path the ValueError is caught and returned as the tool result string "Invalid path parameter: ...", so it usually surfaces as a failed tool result rather than an exception.

Source

Thrown at litellm/proxy/_experimental/mcp_server/openapi_to_mcp_generator.py:121

# Set from MCPServerManager.resolve_openapi_upstream_auth; authoritative
# over every other Authorization source in _merge_openapi_tool_request_headers.
_request_resolved_auth_headers: Final[contextvars.ContextVar[dict[str, str] | None]] = contextvars.ContextVar(
    "_request_resolved_auth_headers", default=None
)


def _sanitize_path_parameter_value(param_value: object, param_name: str) -> str:
    """Ensure path params cannot introduce directory traversal."""
    if param_value is None:
        return ""

    value_str: Final = str(param_value)
    if value_str == "":
        return ""

    normalized_value: Final = value_str.replace("\\", "/")
    if "/" in normalized_value:
        raise ValueError(f"Path parameter '{param_name}' must not contain path separators")

    if any(part in {".", ".."} for part in PurePosixPath(normalized_value).parts):
        raise ValueError(f"Path parameter '{param_name}' cannot include '.' or '..' segments")

    return quote(value_str, safe="")


def load_openapi_spec(filepath: str) -> dict[str, Any]:
    """
    Sync wrapper. For URL specs, use the shared/custom MCP httpx client.
    """
    try:
        # If we're already inside an event loop, prefer the async function.
        asyncio.get_running_loop()
        raise RuntimeError(
            "load_openapi_spec() was called from within a running event loop. "
            "Use 'await load_openapi_spec_async(...)' instead."
        )

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Pass exactly one URL path segment per parameter - strip or restructure slashes before calling the tool.
  2. If the argument came from user input or another file path, split it and use the real segment (or a tool whose OpenAPI path has one parameter per segment).
  3. If the upstream API genuinely accepts an encoded slash inside one segment, verify against the generated tool's input schema; the generator percent-encodes the whole value (quote safe=""), so pre-encoding a slash yourself results in double-encoding - use a slash-free identifier instead.

Example fix

# before
result = await call_mcp_tool(server_id="myapi", tool_name="get_file", arguments={"file_id": "docs/readme.md"})
# -> tool result: "Invalid path parameter: Path parameter 'file_id' must not contain path separators"

# after
result = await call_mcp_tool(server_id="myapi", tool_name="get_file", arguments={"file_id": "readme.md"})
Defensive patterns

Strategy: validation

Validate before calling

def is_single_path_segment(value: object) -> bool:
    s = "" if value is None else str(value)
    return s != "" and "/" not in s and "\\" not in s

assert is_single_path_segment(args["file_id"]), "file_id must be one URL segment"

Type guard

from typing import TypeGuard

def is_safe_path_segment(value: object) -> TypeGuard[str]:
    if not isinstance(value, str) or not value:
        return False
    return "/" not in value and "\\" not in value and value not in (".", "..")

Try / catch

try:
    safe = _sanitize_path_parameter_value(value, name)  # only if calling the generator directly
except ValueError as e:
    raise BadRequest(str(e)) from None
# via the REST API: treat a tool result starting with "Invalid path parameter:" as a client-side 4xx

Prevention

When it happens

Trigger: Calling an MCP tool generated from an OpenAPI spec with a path parameter whose value contains / or \, e.g. arguments={"file_id": "docs/readme"} for path /files/{file_id}; passing a Windows path (C:\x\y) or a value whose str() contains separators (a list ['a','b'] stringifies to a/b).

Common situations: Passing filenames with directories or Windows paths to REST-backed MCP tools; passing a full URL where only one segment was expected; passing non-string values (lists, objects) whose string form contains slashes; porting curl examples that embed slashes into tool args.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/6e13ada45a32e004. Report an issue: GitHub.