{"record":{"id":"a26639a395641ab0","repo":"stalwartlabs/stalwart","slug":"failed-to-start-event-collector","errorCode":null,"errorMessage":"Failed to start event collector","messagePattern":"Failed to start event collector","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/trc/src/ipc/collector.rs","lineNumber":87,"sourceCode":"const SMTP_CONN_END: usize = EventType::Smtp(SmtpEvent::ConnectionEnd).to_id() as usize;\nconst MANAGE_SIEVE_CONN_START: usize =\n    EventType::ManageSieve(ManageSieveEvent::ConnectionStart).to_id() as usize;\nconst MANAGE_SIEVE_CONN_END: usize =\n    EventType::ManageSieve(ManageSieveEvent::ConnectionEnd).to_id() as usize;\nconst EV_ATTEMPT_START: usize = EventType::Delivery(DeliveryEvent::AttemptStart).to_id() as usize;\nconst EV_ATTEMPT_END: usize = EventType::Delivery(DeliveryEvent::AttemptEnd).to_id() as usize;\n\nconst STALE_SPAN_CHECK_WATERMARK: usize = 8000;\nconst SPAN_MAX_HOLD: u64 = 60 * 60 * 24; // 1 day\n\npub(crate) static COLLECTOR_THREAD: LazyLock<Arc<CollectorThread>> = LazyLock::new(|| {\n    Arc::new(\n        Builder::new()\n            .name(\"stalwart-collector\".to_string())\n            .spawn(move || {\n                Collector::default().collect();\n            })\n            .expect(\"Failed to start event collector\"),\n    )\n});\n\nimpl Collector {\n    fn collect(&mut self) {\n        let mut do_continue = true;\n\n        // Update\n        self.update();\n\n        while do_continue {\n            match CHANNEL_FLAGS.swap(0, Ordering::Relaxed) {\n                0 => {\n                    park();\n                }\n                CHANNEL_UPDATE_MARKER..=u64::MAX => {\n                    do_continue = self.update();\n                }","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/stalwartlabs/stalwart/blob/e96200385781a6a9995a8b839ac27d6c75a983ee/crates/trc/src/ipc/collector.rs#L69-L105","documentation":"This panic occurs when the OS fails to spawn the dedicated 'stalwart-collector' thread that runs the event collector loop. `thread::Builder::spawn` returns Err (e.g. resource exhaustion), and the `expect` turns it into a panic during the lazy initialization of the COLLECTOR static.","triggerScenarios":"Thread spawn failure due to hitting the process/thread or memory limits (ulimit -u, cgroup pids.max, out of memory), or an invalid thread builder configuration.","commonSituations":"Running the server in a tightly constrained container with a low pids limit; running out of available memory; RLIMIT_NPROC reached on busy hosts.","solutions":["Raise the container/host thread or process limit (ulimit -u, cgroup pids.max) and restart the server","Free thread/memory resources or increase the container memory allocation","Ensure the binary runs in an environment where thread creation is permitted"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"let handle = Builder::new().name(\"stalwart-collector\".into()).spawn(...)\n    .expect(\"Failed to start event collector\");\n// before spawning, check resource headroom; treat Err as fatal-with-message:\nmatch Builder::new().name(\"stalwart-collector\".into()).spawn(...) {\n    Ok(h) => h,\n    Err(e) => { eprintln!(\"collector spawn failed: {e}\"); return; }\n}","preventionTips":["Set adequate ulimit -u / cgroup pids.max in containers","Monitor thread counts and memory on production hosts","Keep thread creation failures fatal-but-informative rather than silent"],"tags":["threading","resources","collector","startup"],"backgroundTag":"unsupported-platform","analyzedSha":"e96200385781a6a9995a8b839ac27d6c75a983ee","analyzedAt":"2026-09-06T22:07:17.982Z","contentChangedAt":"2026-09-06T22:07:17.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}