PrefectHQ/fastmcp · error · ValueError
HTTP error {response.status_code}: {response.reason_phrase}
Error message
HTTP error {response.status_code}: {response.reason_phrase} - {error_data} What it means
_raise_for_status in the OpenAPI provider converts non-2xx HTTP responses from the upstream API into a ValueError: "HTTP error {status}: {reason} - {body}". The message includes the parsed JSON error body (or raw text if the body is not JSON) so the developer can see exactly what the remote API rejected. It is raised from OpenAPI component run/read paths when the remote server returns an error.
Source
Thrown at fastmcp_slim/fastmcp/server/providers/openapi/components.py:74
logger = get_logger(__name__)
# Default MIME type when no response content type can be inferred
_DEFAULT_MIME_TYPE = "application/json"
def _raise_for_status(response: httpx2.Response) -> None:
"""Raise an OpenAPI-formatted error without relying on client exception types."""
if 200 <= response.status_code < 300:
return
error_message = f"HTTP error {response.status_code}: {response.reason_phrase}"
try:
error_data = response.json()
error_message += f" - {error_data}"
except (json.JSONDecodeError, ValueError):
if response.text:
error_message += f" - {response.text}"
raise ValueError(error_message)
async def _send_request(
client: httpx2.AsyncClient,
request: httpx2.Request,
) -> httpx2.Response:
"""Send a request while preserving transitional legacy-client errors."""
try:
return await client.send(request)
except Exception as exc:
if is_timeout_error(exc):
raise ValueError(f"HTTP request timed out ({type(exc).__name__})") from exc
if is_request_error(exc):
raise ValueError(f"Request error ({type(exc).__name__}): {exc!s}") from exc
raise
def _extract_mime_type_from_route(route: HTTPRoute) -> str:View on GitHub (pinned to 1f02114297)
Solutions
- Read the appended error_data in the message — it usually states the upstream cause (invalid key, missing field, etc.)
- Verify and refresh the API credentials/config used by the OpenAPI provider
- Check that tool call arguments satisfy the operation's required parameters and types
- Confirm the base_url/server URL in the OpenAPI spec config is correct and reachable
- Retry with backoff on transient 429/5xx responses
Example fix
// before
result = await tool.run({"city": city}) # ValueError: HTTP error 401: Unauthorized - {...}
// after
headers = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
provider = OpenAPIProvider(openapi_spec=spec, client=client_with_headers(headers))
# then retry the call once credentials are fixed Defensive patterns
Strategy: try-catch
Validate before calling
resp = await client.get(f"{base_url}/health")
if resp.status_code != 200:
raise RuntimeError(f"upstream API unhealthy: {resp.status_code}") Type guard
def is_retryable_status(status_code: int) -> bool:
return status_code == 429 or status_code >= 500 Try / catch
try:
result = await tool.run(args)
except ValueError as e:
if "HTTP error 429" in str(e) or "HTTP error 5" in str(e):
await asyncio.sleep(backoff)
result = await tool.run(args)
else:
logger.error(f"upstream rejected request: {e}")
raise Prevention
- Inspect the error body appended to the message for the upstream cause
- Rotate/verify API credentials before they expire
- Validate tool call arguments against the operation's schema before invoking
- Confirm base_url in the OpenAPI config points at a reachable environment
- Add retry with backoff for 429/5xx responses only
When it happens
Trigger: Calling a tool/resource backed by an OpenAPI operation when the upstream HTTP API returns 4xx/5xx: bad or expired auth credentials, malformed request parameters generated from the tool call arguments, a wrong base_url in the OpenAPI config, rate limiting (429), or the downstream service being down (5xx).
Common situations: Expired API keys after rotation; calling tools whose required parameters were omitted or sent with wrong types; pointing fastmcp at a staging URL that no longer exists (404); gateway/proxy errors (502/503); the response body revealing auth or validation details from the upstream service.
Related errors
- HTTP request timed out ({type(exc).__name__})
- Request error ({type(exc).__name__}): {exc!s}
- Unexpected authorization response: {response.status_code}
- str(e)
- OIDC discovery for issuer {issuer!r} failed: {e}
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/4ee49cc43fb1abb4.
Report an issue: GitHub.