{"record":{"id":"eb73e8f68eee4f29","repo":"openai/codex","slug":"luna-responses-websocket-failed-0","errorCode":null,"errorMessage":"Luna Responses WebSocket failed: {0}","messagePattern":"Luna Responses WebSocket failed: (.+?)","errorType":"exception","errorClass":"LunaSamplerError","httpStatus":null,"severity":"error","filePath":"codex-rs/ext/guardian-v2/src/async_scorer/sampler.rs","lineNumber":113,"sourceCode":"    pub parent_compaction: Option<ResponseItem>,\n    /// Current parent model's encrypted-compaction compatibility hash.\n    pub parent_compaction_hash: Option<String>,\n    /// Strict JSON schema constraining the model response.\n    pub output_schema: Value,\n    /// Reasoning budget explicitly selected for this request.\n    pub reasoning_effort: ReasoningEffort,\n    /// Owning turn identifier used for request attribution.\n    pub turn_id: String,\n}\n\n/// Failures returned while connecting or sampling the Luna model.\n#[derive(Debug, Error)]\npub enum LunaSamplerError {\n    /// The thread's provider or scoped credentials could not be resolved.\n    #[error(\"could not resolve the Luna model provider: {0}\")]\n    Provider(#[source] CodexErr),\n    /// The Responses WebSocket could not be opened or streamed.\n    #[error(\"Luna Responses WebSocket failed: {0}\")]\n    Api(#[source] ApiError),\n    /// The provider's WebSocket connect deadline elapsed.\n    #[error(\"Luna Responses WebSocket connection timed out\")]\n    ConnectionTimeout,\n    /// The response did not contain an assistant text value.\n    #[error(\"Luna response did not contain assistant output\")]\n    MissingOutput,\n    /// The response exceeded the bounded output limit.\n    #[error(\"Luna response exceeded the output limit\")]\n    OutputTooLarge,\n    /// A newer classification replaced this request when the pool was full.\n    #[error(\"Luna request was superseded by a newer classification\")]\n    Superseded,\n}\n\nstruct PooledConnection {\n    connection: ResponsesWebsocketConnection,\n    // The bridge routes by thread ID, so each socket needs its own identity.","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/ext/guardian-v2/src/async_scorer/sampler.rs#L95-L131","documentation":"Wraps an ApiError raised while opening or streaming the Luna Responses WebSocket: connect failures, stream_request errors, and event-receive errors. The sampler already retries retryable variants (Stream, Retryable, ServerOverloaded, transport timeout/connection, 5xx/429, 401 with auth recovery) up to 2 times, so this escaping means non-retryable or retries exhausted. The nested ApiError discriminates HTTP status vs transport vs stream.","triggerScenarios":"LunaSampler::sample/connect when the endpoint returns 4xx (quota exceeded, usage not included, invalid request, policy violations), the WS stream closes mid-response, or retryable errors persist past MAX_SAMPLING_RETRIES (2).","commonSituations":"Account lacks access to the classifier model or the responses_websockets beta; org quota hit; request rejected by content policy; flaky proxy killing upgraded connections.","solutions":["Read the nested ApiError: Api/QuotaExceeded/UsageNotIncluded are account or entitlement problems; Stream points at connection instability.","Fix entitlements (model access, responses_websockets=2026-02-06 beta) or the request payload as indicated.","For stream or transport errors, check proxies, custom CAs, and WebSocket upgrade support.","Retry later for 5xx/429 once quotas reset."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match err {\n    LunaSamplerError::Api(ApiError::Stream(_) | ApiError::ServerOverloaded | ApiError::Retryable { .. }) => retry_with_backoff().await,\n    LunaSamplerError::Api(ApiError::Api { status, .. } | ApiError::Transport(TransportError::Http { status, .. }))\n        if status.is_server_error() || status == StatusCode::TOO_MANY_REQUESTS => retry_with_backoff().await,\n    _ => return Err(err),\n}","preventionTips":["Remember the sampler already retried twice before surfacing this — caller retries should be sparse.","Act on the nested ApiError: quota/entitlement variants need account fixes, not retries.","Keep proxies and custom CAs configured for wss:// handshakes."],"tags":["rust","websocket","api","guardian","codex"],"backgroundTag":"websocket-request-failed","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}