{"record":{"id":"afb531c64599253e","repo":"zeroclaw-labs/zeroclaw","slug":"acp-elicitation-create-timed-out-after-timeout","errorCode":null,"errorMessage":"ACP elicitation/create timed out after {timeout:?}","messagePattern":"ACP elicitation/create timed out after (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-channels/src/acp_channel.rs","lineNumber":152,"sourceCode":"        let req = ElicitationRequest {\n            session_id: self.session_id.clone(),\n            mode: ElicitationMode::Form,\n            message: question.to_string(),\n            requested_schema: single_select_schema(choices),\n        };\n        debug_assert!(\n            matches!(req.mode, ElicitationMode::Form),\n            \"Phase 1 must not emit URL-mode elicitation\"\n        );\n\n        let params = serde_json::to_value(&req)?;\n        let call = self.rpc.request(\"elicitation/create\", params);\n        let response_value = match tokio::time::timeout(timeout, call).await {\n            Ok(Ok(value)) => value,\n            Ok(Err(e)) => {\n                anyhow::bail!(\"ACP elicitation/create failed: {} ({})\", e.message, e.code)\n            }\n            Err(_) => anyhow::bail!(\"ACP elicitation/create timed out after {timeout:?}\"),\n        };\n\n        let parsed: ElicitationResponse = serde_json::from_value(response_value)\n            .map_err(|e| anyhow::Error::msg(format!(\"malformed elicitation response: {e}\")))?;\n        match parsed {\n            ElicitationResponse::Accept { content } => {\n                let text =\n                    zeroclaw_api::elicitation::decode_single_select_accept(&content, choices)?;\n                Ok(Some(text))\n            }\n            ElicitationResponse::Decline | ElicitationResponse::Cancel => Ok(None),\n        }\n    }\n}\n\nimpl ::zeroclaw_api::attribution::Attributable for AcpChannel {\n    fn role(&self) -> ::zeroclaw_api::attribution::Role {\n        ::zeroclaw_api::attribution::Role::Channel(","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/acp_channel.rs#L134-L170","documentation":"The client never answered the elicitation/create request within the caller-supplied timeout. ZeroClaw wraps every elicitation call in tokio::time::timeout so an unresponsive client (user walked away, IDE closed, transport stalled) cannot park the agent turn forever. The elapsed Duration is included in the message.","triggerScenarios":"request_choice takes the elicitation path and no JSON-RPC response arrives before the Duration passed to request_choice elapses — the user leaves the form open, the client process exits without cancelling, or the back channel silently dies.","commonSituations":"Timeouts sized for network round-trips instead of human response time; modal dialogs hidden behind other windows; laptop sleep mid-prompt; dead stdio/WebSocket transport that never delivers the response.","solutions":["Raise the timeout passed to request_choice to comfortably exceed expected human response time (minutes, not seconds, for interactive prompts).","Verify the ACP client process and transport are alive; a dead back channel can never deliver a response.","Treat this error as a cancellation (None) in the caller so the agent proceeds without user input instead of failing.","If prompts routinely expire, pre-ask availability or route the question through a channel with push notifications."],"exampleFix":"// before\nlet pick = ch.request_choice(\"Deploy to prod?\", &choices, Duration::from_secs(10)).await?;\n\n// after\nlet pick = match ch.request_choice(\"Deploy to prod?\", &choices, Duration::from_secs(300)).await {\n    Ok(opt) => opt,\n    Err(e) if e.to_string().contains(\"timed out\") => {\n        tracing::warn!(error = %e, \"no answer in time; treating as cancel\");\n        None\n    }\n    Err(e) => return Err(e),\n};","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match ch.request_choice(q, &choices, timeout).await {\n    Ok(opt) => opt,\n    Err(e) if e.to_string().contains(\"timed out\") => {\n        // one re-ask, then treat as user cancel\n        ch.request_choice(q, &choices, timeout).await.unwrap_or(None)\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Size prompt timeouts for human response time, not network time","Cancel in-flight prompts on session/stop so timeouts do not race teardown","Distinguish timeout (retry or default) from transport failure (surface immediately)"],"tags":["rust","acp","elicitation","timeout","tokio","request-choice"],"backgroundTag":"request-timeout","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}