Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/_components/error-hierarchy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ ToolkitError # (Abstract base class)
├── RetryableToolError # Tool can be retried with extra context
├── ContextRequiredToolError # Additional context needed before retry
├── FatalToolError # Unhandled bugs in the tool implementation
├── NetworkTransportError # No HTTP response received (timeout, DNS, TLS, etc.)
└── UpstreamError # HTTP/API errors from external services
└── UpstreamRateLimitError # Rate limiting errors from service
`}</code>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ def fetch_data(
return response.json()
```

The HTTP error adapter routes exceptions from `httpx` and `requests` based on whether the client received a complete response:

- **Real HTTP responses** (4xx/5xx) → `UpstreamError` (with `status_code`). 429 becomes `UpstreamRateLimitError`.
- **No response received** (connect/read timeouts, DNS failures, connection errors, TLS handshake failures, decoding errors, redirect-loop exhaustion) → `NetworkTransportError` with `status_code=None`. Classified by `ErrorKind` as `NETWORK_TRANSPORT_RUNTIME_TIMEOUT`, `NETWORK_TRANSPORT_RUNTIME_UNREACHABLE`, or `NETWORK_TRANSPORT_RUNTIME_UNMAPPED`.
- **Client construction bugs** (`InvalidURL`, `UnsupportedProtocol`, `MissingSchema`, `InvalidSchema`, `InvalidHeader`, `InvalidProxyURL`, `URLRequired`, `SSLError`) → `FatalToolError`. These are not retryable and typically indicate a tool-authoring mistake (hardcoded invalid URL, schema, or header) or a local TLS configuration issue. If your tool accepts caller-provided URLs or headers and passes them directly to the HTTP client without validation, invalid caller input is also routed here. Validate caller-supplied values before use.

### Explicit error adapters

For tools using specific SDKs, you can specify error adapters explicitly:
Expand Down
15 changes: 15 additions & 0 deletions app/en/guides/tool-calling/error-handling/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ def handle_tool_error(error: OutputError) -> None:
elif error_kind.startswith("UPSTREAM_"):
# The tool encountered an error from an upstream service
print(error.message)
elif error_kind.startswith("NETWORK_TRANSPORT_"):
# The HTTP request never received a complete response (timeout, DNS
# failure, TLS handshake, etc.). These are typically transient and
# safe to retry.
print(error.message)


client = Arcade() # Automatically finds the `ARCADE_API_KEY` env variable
Expand Down Expand Up @@ -124,6 +129,11 @@ function handleToolError(error) {
} else if (errorKind.startsWith("UPSTREAM_")) {
// The tool encountered an error from an upstream service
console.log(error.message);
} else if (errorKind.startsWith("NETWORK_TRANSPORT_")) {
// The HTTP request never received a complete response (timeout, DNS
// failure, TLS handshake, etc.). These are typically transient and
// safe to retry.
console.log(error.message);
}
}

Expand Down Expand Up @@ -203,6 +213,11 @@ import org.slf4j.LoggerFactory;
} else if (errorKind.asString().startsWith("UPSTREAM_")) {
// The tool encountered an error from an upstream service
logger.error(error.message());
} else if (errorKind.asString().startsWith("NETWORK_TRANSPORT_")) {
// The HTTP request never received a complete response (timeout, DNS
// failure, TLS handshake, etc.). These are typically transient and
// safe to retry.
logger.error(error.message());
}
}

Expand Down
8 changes: 8 additions & 0 deletions app/en/references/mcp/python/errors/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,14 @@ Error from an upstream service the tool depends on.

Rate limit error from an upstream service.

### `NetworkTransportError`

Error raised when an HTTP request never received a complete response (for example, connect/read timeouts, DNS failures, TLS handshake errors, decoding errors, redirect-loop exhaustion). Sibling of `UpstreamError` under `ToolExecutionError`. Unlike `UpstreamError`, `status_code` is always `None` because the client received no response. Classified by `ErrorKind` into one of:

- `NETWORK_TRANSPORT_RUNTIME_TIMEOUT`—pool, connect, or read timeouts
- `NETWORK_TRANSPORT_RUNTIME_UNREACHABLE`—DNS, connection, TLS handshake, or remote-protocol failures
- `NETWORK_TRANSPORT_RUNTIME_UNMAPPED`—decode errors, redirect exhaustion, and other transport-level fallbacks

### `ContextRequiredToolError`

Error raised when a tool requires a context that was not provided.
Expand Down
Loading