{"record":{"id":"24930a669bfb577d","repo":"actix/actix","slug":"failed-to-spawn-thread","errorCode":null,"errorMessage":"failed to spawn thread","messagePattern":"failed to spawn thread","errorType":"panic","errorClass":"panic","httpStatus":null,"severity":"error","filePath":"actix/src/sync.rs","lineNumber":147,"sourceCode":"        F: Fn() -> A + Send + Sync + 'static,\n        BF: FnMut() -> thread::Builder,\n    {\n        let factory = Arc::new(factory);\n        let (sender, receiver) = cb_channel::unbounded();\n        let (tx, rx) = channel::channel(0);\n\n        for _ in 0..threads {\n            let f = Arc::clone(&factory);\n            let sys = System::current();\n            let actor_queue = receiver.clone();\n            let inner_rx = rx.sender_producer();\n\n            thread_builder_factory()\n                .spawn(move || {\n                    System::set_current(sys);\n                    SyncContext::new(f, actor_queue, inner_rx).run();\n                })\n                .expect(\"failed to spawn thread\");\n        }\n\n        System::current().arbiter().spawn(Self {\n            queue: Some(sender),\n            msgs: rx,\n        });\n\n        Addr::new(tx)\n    }\n}\n\nimpl<A> Actor for SyncArbiter<A>\nwhere\n    A: Actor<Context = SyncContext<A>>,\n{\n    type Context = Context<Self>;\n}\n","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/actix/actix/blob/36e5d97e41ebd16431c709365e6942db08d867d7/actix/src/sync.rs#L129-L165","documentation":"SyncArter's start_with_thread_builder panics when std::thread::Builder::spawn fails to create the sync actor's OS thread. Thread spawn failures typically come from resource exhaustion (hitting thread or memory limits) or OS-level restrictions. The .expect() makes this a hard abort of the sync actor startup.","triggerScenarios":"Calling SyncArter::start / start_with_thread_builder when the OS cannot spawn a thread — process at its thread limit (ulimit -u, cgroup pids.max), out of memory for the new stack, or running in a restricted sandbox.","commonSituations":"Containers with low pids limits; applications spawning very large numbers of sync actors; low ulimit settings in CI or Docker; thread stack size requests too large for available memory.","solutions":["Raise the thread/process limit: ulimit -u, or container --pids-limit / cgroup pids.max.","Reduce the number of concurrently started sync actors, or pool them.","Check memory availability; lower thread stack_size if a large custom stack was configured.","Inspect sandbox/seccomp policies that may block clone()/pthread_create.","In application code, pre-check system capacity or fall back to regular (non-sync) actors."],"exampleFix":"// before (container)\ndocker run --pids-limit 16 myapp\n\n// after\ndocker run --pids-limit 512 myapp","handlingStrategy":"fallback","validationCode":"// Pre-check thread capacity before starting sync actors\nlet limits = fs::read_to_string(\"/proc/self/limits\")\n    .map(|l| l.contains(\"Max processes\"))\n    .unwrap_or(true);\nassert!(limits, \"process/thread limit file unreadable — verify ulimits\");","typeGuard":null,"tryCatchPattern":"// spawn() returns io::Result; replicate the check yourself before expect\nmatch thread_builder.spawn(worker) {\n    Ok(h) => h,\n    Err(e) => { log::error!(\"thread spawn failed: {e}\"); return; }\n}","preventionTips":["Raise ulimit -u and container --pids-limit before running sync-actor-heavy workloads","Reduce the number of concurrent sync actors; pool or reuse them","Lower custom stack_size on thread builders when memory is tight","Check sandbox/seccomp policies that could block thread creation"],"tags":["actix","sync-actor","thread","resource-exhaustion"],"backgroundTag":"resource-not-found","analyzedSha":"36e5d97e41ebd16431c709365e6942db08d867d7","analyzedAt":"2026-09-11T16:51:51.370Z","contentChangedAt":"2026-09-11T16:51:51.370Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}