rust-lang/rust-analyzer · critical
failed to spawn thread
Error message
failed to spawn thread
What it means
stdx::thread::spawn creates a named thread with the configured stack size and intent, and panics if the OS refuses to spawn it (std::thread::Builder::spawn returns Err, typically ResourceTemporarilyUnavailable or PermDenied). The doc comment explicitly states it panics on failure — threads are considered essential in rust-analyzer.
Source
Thrown at crates/stdx/src/thread.rs:34
//! and every entry point to creating a thread requires a [`ThreadIntent`] upfront.
use std::fmt;
mod intent;
mod pool;
pub use intent::ThreadIntent;
pub use pool::Pool;
/// # Panics
///
/// Panics if failed to spawn the thread.
pub fn spawn<F, T>(intent: ThreadIntent, name: String, f: F) -> JoinHandle<T>
where
F: (FnOnce() -> T) + Send + 'static,
T: Send + 'static,
{
Builder::new(intent, name).spawn(f).expect("failed to spawn thread")
}
pub const DEFAULT_STACK_SIZE: usize = 16 * 1024 * 1024;
pub struct Builder {
intent: ThreadIntent,
inner: jod_thread::Builder,
allow_leak: bool,
}
impl Builder {
#[must_use]
pub fn new(intent: ThreadIntent, name: impl Into<String>) -> Self {
Self {
intent,
inner: jod_thread::Builder::new().name(name.into()).stack_size(DEFAULT_STACK_SIZE),
allow_leak: false,
}View on GitHub (pinned to e8f7e90aa3)
Solutions
- Raise the process/thread limit: check `ulimit -u`, container pids limit (docker --pids-limit, Kubernetes pod pids), and increase it.
- Find and fix thread leaks in the application (threads spawned per request/task without joining).
- Reduce default stack size (stdx::thread::Builder stack size, default 16MiB) if memory-bound spawning fails.
- Free system resources (memory pressure, other processes) or restart the editor/LSP session.
Example fix
// before
stdx::thread::spawn(ThreadIntent::Worker, name, closure); // panics if spawn fails
// after
match stdx::thread::Builder::new(ThreadIntent::Worker, name).spawn(closure) {
Ok(handle) => handle,
Err(err) => { log::error!("thread spawn failed: {err}"); return; } // graceful fallback
} Defensive patterns
Strategy: fallback
Try / catch
match stdx::thread::Builder::new(intent, name).spawn(f) {
Ok(h) => h,
Err(e) => { log::error!("spawn failed: {e}"); /* handle degraded mode */ }
} Prevention
- Raise thread/pids limits in containers and dev machines
- Fix thread leaks: join or bound spawned workers
- Lower configured stack size when memory is the constraint
- Monitor thread counts in long-running LSP sessions
When it happens
Trigger: Calling stdx::thread::spawn when the process has exhausted thread resources: hitting RLIMIT_NPROC / pthread_create EAGAIN, too many threads already running, or insufficient memory for the 16MiB default stack.
Common situations: Long-running rust-analyzer sessions leaking threads; containerized environments (Docker/K8s) with low pids limits (e.g. pids.max); heavily loaded CI machines; spawning many parallel tasks without backpressure.
Related errors
- We explicitly do not provide canonicalization API, as that i
- bad kind {other}
- bad spacing {other}
- bad tag: {other}
- profiler already started
AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03).
Data as JSON: /api/errors/3637933c82f2f3e3.
Report an issue: GitHub.