{"record":{"id":"528291dfb62ee9ba","repo":"zed-industries/zed","slug":"failed-to-spawn-drop-thread","errorCode":null,"errorMessage":"failed to spawn drop thread","messagePattern":"failed to spawn drop thread","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/language/src/syntax_map.rs","lineNumber":56,"sourceCode":"pub struct SyntaxSnapshot {\n    layers: SumTree<SyntaxLayerEntry>,\n    parsed_version: clock::Global,\n    interpolated_version: clock::Global,\n    language_registry_version: usize,\n    update_count: usize,\n}\n\n// Dropping deep treesitter Trees can be quite slow due to deallocating lots of memory.\n// To avoid blocking the main thread, we offload the drop operation to a background thread.\nimpl Drop for SyntaxSnapshot {\n    fn drop(&mut self) {\n        static DROP_TX: LazyLock<std::sync::mpsc::Sender<SumTree<SyntaxLayerEntry>>> =\n            LazyLock::new(|| {\n                let (tx, rx) = std::sync::mpsc::channel();\n                std::thread::Builder::new()\n                    .name(\"SyntaxSnapshot::drop\".into())\n                    .spawn(move || while let Ok(_) = rx.recv() {})\n                    .expect(\"failed to spawn drop thread\");\n                tx\n            });\n        // This does allocate a new Arc, but it's cheap and avoids blocking the main thread without needing to use an `Option` or `MaybeUninit`.\n        let _ = DROP_TX.send(std::mem::replace(\n            &mut self.layers,\n            SumTree::from_summary(SyntaxLayerSummary {\n                min_depth: Default::default(),\n                max_depth: Default::default(),\n                // Deliberately bogus anchors, doesn't matter in this context\n                range: Anchor::min_min_range_for_buffer(BufferId::new(1).unwrap()),\n                last_layer_range: Anchor::min_min_range_for_buffer(BufferId::new(1).unwrap()),\n                last_layer_language: Default::default(),\n                contains_unknown_injections: Default::default(),\n            }),\n        ));\n    }\n}\n","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/zed-industries/zed/blob/9d272b036335401f339d024ea94968fd51016c40/crates/language/src/syntax_map.rs#L38-L74","documentation":"Panics in SyntaxSnapshot::drop's LazyLock initializer when std::sync::mpsc::channel creation succeeds but the dedicated drop thread (which offloads slow tree-sitter Tree deallocation) cannot be spawned. Spawn failure is close to impossible on desktop platforms (thread exhaustion / resource limits), but if it happens, every snapshot drop on that process panics because the sender can never be constructed.","triggerScenarios":"Thrown at crates/language/src/syntax_map.rs:53 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Check for thread/resource exhaustion (ulimit, RLIMIT_NPROC) on the failing system","Fall back to dropping trees inline on the current thread when the channel/spawn fails, trading latency for correctness","Initialize the drop thread eagerly at startup and abort with a clear diagnostic instead of panicking on first snapshot drop"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"9d272b036335401f339d024ea94968fd51016c40","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}