{"record":{"id":"479f827127519d23","repo":"Kuberwastaken/claurst","slug":"lsp-server-stdout-not-available","errorCode":null,"errorMessage":"LSP server stdout not available","messagePattern":"LSP server stdout not available","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-rust/crates/core/src/lsp.rs","lineNumber":223,"sourceCode":"            cmd.creation_flags(0x0800_0000u32);\r\n        }\r\n\r\n        let mut child = cmd.spawn().map_err(|e| {\r\n            anyhow::anyhow!(\r\n                \"Failed to start LSP server '{}': {}\",\r\n                config.command,\r\n                e\r\n            )\r\n        })?;\r\n\r\n        let stdin = child\r\n            .stdin\r\n            .take()\r\n            .ok_or_else(|| anyhow::anyhow!(\"LSP server stdin not available\"))?;\r\n        let stdout = child\r\n            .stdout\r\n            .take()\r\n            .ok_or_else(|| anyhow::anyhow!(\"LSP server stdout not available\"))?;\r\n\r\n        let pending: PendingMap = Arc::new(DashMap::new());\r\n        let diagnostics: Arc<DashMap<String, Vec<LspDiagnostic>>> =\r\n            Arc::new(DashMap::new());\r\n\r\n        let writer = Arc::new(Mutex::new(BufWriter::new(stdin)));\r\n        let pending_clone = pending.clone();\r\n        let diagnostics_clone = diagnostics.clone();\r\n        let server_name = config.name.clone();\r\n\r\n        // Consume stderr in the background so the OS pipe buffer never fills up\r\n        if let Some(stderr) = child.stderr.take() {\r\n            let name = server_name.clone();\r\n            tokio::spawn(async move {\r\n                let mut lines = BufReader::new(stderr).lines();\r\n                while let Ok(Some(line)) = lines.next_line().await {\r\n                    tracing::debug!(\"[LSP SERVER {}] {}\", name, line);\r\n                }\r","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/Kuberwastaken/claurst/blob/b0637c97ec34144387cbf2f74f65df6d16a6cef1/src-rust/crates/core/src/lsp.rs#L205-L241","documentation":"Same as the stdin case but for stdout: `child.stdout.take()` returned `None` in `LspClient::start`, so the client cannot build its response-reader pump. Because `start` always pipes stdout, this is effectively an internal invariant violation or an OS-level pipe-creation failure.","triggerScenarios":"`LspClient::start` with stdout pipes failing to be created by the OS, or the Child handle's stdout already taken before line 220 — not reachable through normal public API usage.","commonSituations":"fd exhaustion (too many open files) preventing pipe creation; heavily sandboxed environments (containers/seccomp) that restrict pipe allocation; modified library code.","solutions":["Retry startup; check and raise the open-file limit (`ulimit -n`) if fd exhaustion is suspected.","Audit sandbox/container policies that may block pipe creation.","Ensure no code path takes stdout from the Child before LspClient::start does.","Report upstream if reproducible under normal conditions."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match LspClient::start(config.clone()).await {\n    Ok(c) => c,\n    Err(e) if e.to_string().contains(\"stdout not available\") => retry_with_backoff(config, 3).await?,\n    Err(e) => return Err(e),\n}","preventionTips":["Avoid exhausting file descriptors; raise ulimit -n for hosts spawning many servers.","Do not intercept the child's stdio handles outside the library.","Retry transiently; escalate to a bug report on reproducible failures."],"tags":["lsp","stdio","internal-error","rust"],"backgroundTag":"internal-invariant-violation","analyzedSha":"b0637c97ec34144387cbf2f74f65df6d16a6cef1","analyzedAt":"2026-09-10T00:24:58.650Z","contentChangedAt":"2026-09-10T00:24:58.650Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}