Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Providers needing extra special cases call extended_http_error_mapper
(same file), which additionally maps 402 to quota_exceeded, 408/504 to
timeout, 413 to context_length_exceeded, and 502/503 to
provider_unavailable.
// Good
ProviderError::authentication(PROVIDER_NAME, "Invalid API key")
// Bad - verbose and error-prone
ProviderError::Authentication {
provider: PROVIDER_NAME,
message: "Invalid API key".to_string(),
}
2. Include Provider Name
// Good - error clearly identifies source
ProviderError::network("openai", "Connection refused")
// Bad - unclear which provider failed
ProviderError::network("unknown", "Connection refused")
3. Preserve Error Context
// Good - execute_request already returns a classified ProviderErrorletresponse = self.pool_manager
.execute_request(&url, method, headers, body)
.await?;
// Bad - erases an existing typed error by reclassifying it as Networkself.pool_manager.execute_request(&url, method, headers, body)
.await
.map_err(|e| ProviderError::network(PROVIDER_NAME, e.to_string()))?
4. Use Specific Error Types
// Good - specific error typeif response.status() == 429 {
returnErr(ProviderError::rate_limit(PROVIDER_NAME, retry_after));
}
// Bad - generic error loses informationif !response.status().is_success() {
returnErr(ProviderError::api_error(PROVIDER_NAME, status, "Failed"));
}
5. Handle All Error Variants in Match
// Good - exhaustive handlingmatch error {
ProviderError::RateLimit { retry_after, .. } => {
ifletSome(delay) = retry_after {
tokio::time::sleep(Duration::from_secs(delay)).await;
}
// Retry...
}
ProviderError::Authentication { .. } => {
// Don't retry, return immediatelyreturnErr(error);
}
e if RetryPolicy
.decide(&router_config, e, retry_context)
.should_retry =>
{
// Retry per decision.delay (see reference/retry-logic.md).// Note: error.is_retryable() is deprecated since 0.6.0.
}
_ => returnErr(error),
}
HTTP to ProviderError Mapping Reference
Canonical behavior of default_http_error_mapper:
HTTP Status
Result
Legacy-retryable
400
invalid_request (message parsed from body)
No
401
authentication ("Invalid API key")
No
403
authentication ("Permission denied")
No
404
model_not_found
No
429
rate_limit (retry-after parsed from body when present)