{"record":{"id":"213db1feec089e2b","repo":"openai/codex","slug":"luna-responses-websocket-connection-timed-out","errorCode":null,"errorMessage":"Luna Responses WebSocket connection timed out","messagePattern":"Luna Responses WebSocket connection timed out","errorType":"exception","errorClass":"LunaSamplerError","httpStatus":null,"severity":"error","filePath":"codex-rs/ext/guardian-v2/src/async_scorer/sampler.rs","lineNumber":116,"sourceCode":"    /// 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.\n    thread_id: String,\n    expires_at: Instant,\n    auth_changes: Option<tokio::sync::watch::Receiver<u64>>,","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/ext/guardian-v2/src/async_scorer/sampler.rs#L98-L134","documentation":"The provider's websocket_connect_timeout elapsed before the Responses WebSocket handshake completed (tokio::time::timeout around ResponsesWebsocketClient::connect). Also produced if the pool's capacity semaphore is closed. The sampler retries this variant up to 2 times before it escapes.","triggerScenarios":"Connecting when the network is slow or blocks WebSocket upgrades (corporate proxy), the provider endpoint is down, or websocket_connect_timeout is too low for the link latency.","commonSituations":"Restrictive egress proxies stalling wss:// handshakes; high-latency VPN; self-hosted gateway with a short timeout; provider incident.","solutions":["Confirm the provider base URL is reachable and supports wss.","Allow WebSocket upgrades through the proxy or firewall.","Raise websocket_connect_timeout for the provider if the link is legitimately slow.","Check for a provider outage — the sampler has already retried twice when this surfaces."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match err {\n    LunaSamplerError::ConnectionTimeout if attempts < 3 => {\n        tokio::time::sleep(backoff(attempts)).await;\n        continue;\n    }\n    _ => return Err(err),\n}","preventionTips":["Verify wss:// reachability through the egress proxy before enabling guardian-v2.","Size websocket_connect_timeout to the link's real RTT.","Prefer failing open (no classification) over blocking turns on persistent timeouts."],"tags":["rust","websocket","timeout","network","guardian"],"backgroundTag":"connection-timeout","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}