{"record":{"id":"071de5468d83af6a","repo":"bevyengine/bevy","slug":"failed-to-spawn-thread","errorCode":null,"errorMessage":"Failed to spawn thread.","messagePattern":"Failed to spawn thread\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/bevy_tasks/src/task_pool.rs","lineNumber":220,"sourceCode":"                            let _destructor = CallOnDrop(on_thread_destroy);\n                            loop {\n                                let res = std::panic::catch_unwind(|| {\n                                    let tick_forever = async move {\n                                        loop {\n                                            local_executor.tick().await;\n                                        }\n                                    };\n                                    block_on(ex.run(tick_forever.or(shutdown_rx.recv())))\n                                });\n                                if let Ok(value) = res {\n                                    // Use unwrap_err because we expect a Closed error\n                                    value.unwrap_err();\n                                    break;\n                                }\n                            }\n                        });\n                    })\n                    .expect(\"Failed to spawn thread.\")\n            })\n            .collect();\n\n        Self {\n            executor,\n            threads,\n            shutdown_tx,\n        }\n    }\n\n    /// Return the number of threads owned by the task pool\n    pub fn thread_num(&self) -> usize {\n        self.threads.len()\n    }\n\n    /// Allows spawning non-`'static` futures on the thread pool. The function takes a callback,\n    /// passing a scope object into it. The scope object provided to the callback can be used\n    /// to spawn tasks. This function will await the completion of all tasks before returning.","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_tasks/src/task_pool.rs#L202-L238","documentation":"TaskPool::new_internal (bevy_tasks task_pool.rs:176-222) spawns one OS thread per worker (num_threads, defaulting to available_parallelism) via thread::Builder::spawn and expects success. The panic means the OS or runtime refused thread creation: thread-count limits (ulimit -u, cgroup pids.max), insufficient memory for thread stacks, or sandbox restrictions on clone.","triggerScenarios":"Creating a TaskPool (Bevy's default TaskPoolPlugin does this at startup with min_total_threads/max_total_threads from TaskPoolOptions) inside a container, CI job, or sandbox with a low process/thread cap; requesting a large num_threads; a very large stack_size exhausting address space.","commonSituations":"Docker/Kubernetes containers with pids limits; CI sandboxes and gVisor/seccomp profiles; embedded or memory-constrained targets; over-tuned TaskPoolOptions in constrained daemons.","solutions":["Raise the OS limit: `ulimit -u` / container pids.max / thread quota","Lower requested threads: TaskPoolBuilder::num_threads, or TaskPoolOptions min_total_threads in the app","Reduce custom stack_size if set very large","Free memory — thread stack allocation failure also triggers this"],"exampleFix":"// before — forces 16 worker threads inside a thread-capped container\nlet pool = TaskPoolBuilder::new().num_threads(16).build();\n\n// after — stay within the container's thread budget\nlet pool = TaskPoolBuilder::new().num_threads(2).build();","handlingStrategy":"fallback","validationCode":"// probe the environment before building a pool in constrained runtimes\nlet max_threads = std::thread::available_parallelism()\n    .map(|n| n.get())\n    .unwrap_or(1);\nlet threads = max_threads.min(2); // stay under container thread caps","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set modest TaskPoolOptions min_total_threads when running in containers/CI","Check `ulimit -u` and cgroup pids.max when integrating Bevy into restricted hosts","Avoid oversized stack_size on 32-bit or memory-constrained targets"],"tags":["bevy","task-pool","threads","os-limits","container","ci","panic"],"backgroundTag":"thread-creation-failed","analyzedSha":"396ca727080776bd313bb892423b7d94e03b81b4","analyzedAt":"2026-08-20T16:12:39.808Z","contentChangedAt":"2026-08-20T16:12:39.808Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}