{"record":{"id":"fb779b8dd7ed5840","repo":"zed-industries/zed","slug":"failed-to-send-sandbox-fallback-authorization-er","errorCode":null,"errorMessage":"Failed to send sandbox fallback authorization: {error}","messagePattern":"Failed to send sandbox fallback authorization: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/agent/src/thread.rs","lineNumber":6266,"sourceCode":"                        // failure reason): it's critical the user can see what\n                        // they're approving to run unsandboxed. The reason is\n                        // surfaced separately by the fallback details / warning.\n                        tool_call: acp::ToolCallUpdate::new(\n                            tool_call_id.clone(),\n                            acp::ToolCallUpdateFields::new(),\n                        )\n                        .meta(\n                            acp_thread::meta_with_sandbox_fallback_authorization(details),\n                        ),\n                        options,\n                        response: response_tx,\n                        context: None,\n                        kind: acp_thread::AuthorizationKind::ActionChoice,\n                    },\n                )))\n            {\n                log::error!(\"Failed to send sandbox fallback authorization: {error}\");\n                return Err(anyhow!(\n                    \"Failed to send sandbox fallback authorization: {error}\"\n                ));\n            }\n\n            let outcome = response_rx\n                .await\n                .map_err(|_| anyhow!(\"authorization channel closed\"))?;\n            ensure_tool_call_authorization_not_interrupted(&outcome)?;\n\n            let option_id = outcome.option_id.0.as_ref();\n            if option_id == acp_thread::SANDBOX_FALLBACK_RETRY_OPTION_ID {\n                return Ok(SandboxFallbackDecision::Retry);\n            }\n            match acp_thread::SandboxPermission::from_id(option_id) {\n                Some(acp_thread::SandboxPermission::AllowOnce) => {\n                    Ok(SandboxFallbackDecision::RunUnsandboxed)\n                }\n                Some(acp_thread::SandboxPermission::AllowThread) => {","sourceCodeStart":6248,"sourceCodeEnd":6284,"githubUrl":"https://github.com/zed-industries/zed/blob/bc538def4545534201bbfcac4e95ac34ea6501b6/crates/agent/src/thread.rs#L6248-L6284","documentation":"When a sandboxed execution fails and the thread asks whether to retry or run unsandboxed, the fallback authorization is sent over the event stream; a failed unbounded_send means the receiver was dropped and this error wraps the send failure. The decision prompt cannot reach the user, so the fallback flow aborts.","triggerScenarios":"The event-stream consumer disappears while a sandbox fallback decision (retry versus run unsandboxed) is pending: UI closed, session dropped, or client disconnected right after the sandbox error.","commonSituations":"Client teardown immediately after a sandbox failure; embedding code that drops the event receiver in error paths; reloads during fallback decisions.","solutions":["Keep the ThreadEvent receiver alive for the thread's whole lifetime, especially across error paths","Treat the error as cancellation: stop the tool call and report the original sandbox failure","Re-establish the session and rerun the tool if the user still wants it","Cancel the thread before tearing down the client so pending prompts resolve"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(err) = fallback_authorization_result {\n    if err.to_string().starts_with(\"Failed to send sandbox fallback authorization\") {\n        // Event consumer is gone: fail the tool call with the original\n        // sandbox error instead of waiting for a decision.\n        return Err(original_sandbox_error);\n    }\n    return Err(err);\n}","preventionTips":["Keep the ThreadEvent receiver alive across error paths, not only happy paths","Treat send failures during fallback as cancellation and stop the tool call","Cancel the thread before tearing down the client so pending prompts resolve","Re-establish the session and rerun the tool if the user still wants it"],"tags":["rust","agent","sandbox","fallback","authorization","channel","lifecycle"],"backgroundTag":null,"analyzedSha":"bc538def4545534201bbfcac4e95ac34ea6501b6","analyzedAt":"2026-08-16T07:30:46.435Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}