mirror of
https://github.com/openai/codex.git
synced 2026-10-20 17:38:45 +00:00
Surface Flex capacity failures as a distinct terminal error (#47967)
## What changed - Recognize `flex_unavailable` in HTTP 429 responses and streamed `error` and `response.failed` events. End normal turns without retries and report `Flex capacity unavailable.` - Expose `flexUnavailable` through the core and app-server protocols and generated schemas and SDK types. - Keep Flex capacity failures eligible for Guardian review and sampler retries, with a distinct telemetry classification. - Map unexpected HTTP responses to `HttpConnectionFailed`, preserving their status codes. ## Testing Add regression coverage for terminal Flex failures over HTTP, SSE, and WebSocket, HTTP 504 status preservation after a stream retry, and protocol serialization. Update Guardian retry and sampler recovery tests to cover Flex failures. GitOrigin-RevId: f2e03a6d2d36a6d9748c35952e40397f8670d121
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use crate::TransportError;
|
||||
use crate::error::ApiError;
|
||||
use crate::error::parse_flex_unavailable;
|
||||
use crate::rate_limits::parse_promo_message;
|
||||
use crate::rate_limits::parse_rate_limit_for_limit;
|
||||
use crate::rate_limits::parse_rate_limit_reached_type;
|
||||
@@ -30,6 +31,7 @@ pub fn map_api_error(err: ApiError) -> CodexErr {
|
||||
| ApiError::ContextWindowExceeded
|
||||
| ApiError::QuotaExceeded
|
||||
| ApiError::UsageNotIncluded
|
||||
| ApiError::FlexUnavailable
|
||||
| ApiError::RateLimit(_)
|
||||
| ApiError::InvalidRequest { .. }
|
||||
| ApiError::InvalidPrompt { .. }
|
||||
@@ -55,6 +57,7 @@ fn map_api_error_details(err: ApiError) -> CodexErr {
|
||||
}
|
||||
ApiError::Stream(msg) => CodexErr::Stream(msg),
|
||||
ApiError::ServerOverloaded { .. } => CodexErr::ServerOverloaded,
|
||||
ApiError::FlexUnavailable => CodexErr::new(CodexErrorDetails::FlexUnavailable),
|
||||
ApiError::Api { status, message } => {
|
||||
let user_message = api_error_user_message(status, &message);
|
||||
CodexErr::UnexpectedStatus(UnexpectedResponseError {
|
||||
@@ -174,6 +177,11 @@ fn map_api_error_details(err: ApiError) -> CodexErr {
|
||||
} else if status == http::StatusCode::INTERNAL_SERVER_ERROR {
|
||||
CodexErr::InternalServerError
|
||||
} else if status == http::StatusCode::TOO_MANY_REQUESTS {
|
||||
if let Ok(body) = serde_json::from_str::<Value>(&body_text)
|
||||
&& let Some(error) = body.get("error").and_then(parse_flex_unavailable)
|
||||
{
|
||||
return map_api_error(error);
|
||||
}
|
||||
if let Ok(err) = serde_json::from_str::<UsageErrorResponse>(&body_text) {
|
||||
if err.error.error_type.as_deref() == Some("usage_limit_reached") {
|
||||
let limit_id = extract_header(headers.as_ref(), ACTIVE_LIMIT_HEADER);
|
||||
|
||||
Reference in New Issue
Block a user