{"record":{"id":"b66e616eb0ebe4ce","repo":"xai-org/grok-build","slug":"failed-to-spawn-acp-stdin-reader-thread","errorCode":null,"errorMessage":"failed to spawn acp-stdin reader thread","messagePattern":"failed to spawn acp-stdin reader thread","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-acp-lib/src/stdin_reader.rs","lineNumber":101,"sourceCode":"    // parks in a blocking read holding the global `StdinLock`. After this, any\n    // other `std::io::stdin()` read in the process EOFs immediately instead of\n    // deadlocking. `None` means we couldn't isolate (we fall back to reading\n    // `std::io::stdin()` directly — no worse than before).\n    #[cfg(windows)]\n    let private_stdin: Option<std::fs::File> = isolate_process_stdin();\n\n    std::thread::Builder::new()\n        .name(\"acp-stdin\".to_string())\n        .spawn(move || {\n            #[cfg(windows)]\n            if let Some(file) = private_stdin {\n                forward_lines(std::io::BufReader::new(file), &tx);\n                return;\n            }\n            let stdin = std::io::stdin();\n            forward_lines(stdin.lock(), &tx);\n        })\n        .expect(\"failed to spawn acp-stdin reader thread\");\n    rx\n}\n\n/// Read `\\n`-delimited lines from `reader` and forward each on `tx` — via\n/// [`normalize_json_line`], so bytes are verbatim except for the lines that\n/// workaround rewrites (terminator always preserved) — until EOF, a read\n/// error, or the receiver is dropped.\nfn forward_lines<R: BufRead>(mut reader: R, tx: &mpsc::Sender<Vec<u8>>) {\n    let mut line = Vec::new();\n    loop {\n        line.clear();\n        match reader.read_until(b'\\n', &mut line) {\n            // EOF or a fatal read error: return, dropping `tx` closes the channel.\n            Ok(0) | Err(_) => break,\n            Ok(_) => {}\n        }\n        let normalized = normalize_json_line(std::mem::take(&mut line));\n        // `blocking_send` parks this thread (not a runtime worker) when the","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-acp-lib/src/stdin_reader.rs#L83-L119","documentation":"spawn_stdin_line_reader spawns an OS thread that forwards stdin lines to the ACP pipeline; it calls .expect(\"failed to spawn acp-stdin reader thread\"), so the process panics if std::thread::spawn fails. Spawn failure means the OS refused to create a thread - almost always resource exhaustion.","triggerScenarios":"Calling spawn_stdin_line_reader() when the process has hit the thread/process rlimit (ulimit -u), the OS is out of memory for a new stack, or cgroup/pid limits (pids.max) are exhausted.","commonSituations":"Containers with low pids cgroup limits; CI machines with restrictive ulimits; a thread leak elsewhere in the app exhausting the allowance before ACP startup.","solutions":["Raise limits: ulimit -u / ulimit -v, or the container's pids.max / RLIMIT_NPROC","Audit and fix thread leaks so the process is not at its thread cap at startup","Wrap startup in catch_unwind or pre-flight check resource headroom and fail with a clear message","Reduce concurrent subsystems spawning threads before ACP initialization"],"exampleFix":"// before\nlet rx = spawn_stdin_line_reader(); // panics under thread exhaustion\n// after\nlet rx = std::panic::catch_unwind(spawn_stdin_line_reader)\n    .map_err(|_| anyhow!(\"cannot spawn stdin reader: thread limit reached\"))?;","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"let rx = std::panic::catch_unwind(spawn_stdin_line_reader)\n    .map_err(|_| anyhow!(\"stdin reader thread could not be spawned (resource limits?)\"))?;","preventionTips":["Check ulimit -u / cgroup pids.max before launching in constrained environments","Fix thread leaks so the process has headroom at ACP startup","Pre-warm threads early and fail fast at startup, not mid-session","Monitor thread count in long-running processes"],"tags":["threading","panics","resource-limits","rust"],"backgroundTag":"thread-spawn-failed","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}