{"record":{"id":"acbc6d0c81912438","repo":"tracel-ai/burn","slug":"dataloader-worker-thread-should-be-alive","errorCode":null,"errorMessage":"Dataloader worker thread should be alive","messagePattern":"Dataloader worker thread should be alive","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-core/src/data/dataloader/multithread.rs","lineNumber":255,"sourceCode":"}\n\nimpl<I, O> DataLoader<O> for MultiThreadDataLoader<I, O>\nwhere\n    I: Send + Sync + Clone + 'static,\n    O: Send + 'static + std::fmt::Debug,\n{\n    fn iter<'a>(&'a self) -> Box<dyn DataLoaderIterator<O> + 'a> {\n        let workers = self.workers();\n\n        let (sender, receiver) = mpsc::sync_channel::<Message<O>>(MAX_QUEUED_ITEMS);\n        let unit: Option<String> = Some(\"items\".to_string());\n\n        let mut progresses = Vec::with_capacity(workers.senders.len());\n        for (command_sender, &num_items) in workers.senders.iter().zip(workers.item_counts.iter()) {\n            progresses.push(Progress::new(0, num_items, unit.clone()));\n            command_sender\n                .send(sender.clone())\n                .expect(\"Dataloader worker thread should be alive\");\n        }\n        let num_workers = workers.senders.len();\n\n        // Drop our sender so the channel disconnects once every worker is done.\n        drop(sender);\n\n        Box::new(MultiThreadsDataloaderIterator::new(\n            receiver,\n            num_workers,\n            progresses,\n        ))\n    }\n\n    fn num_items(&self) -> usize {\n        // For num_items, we can directly use the dataset size without\n        // necessarily initializing the full loader\n        self.dataset.len()\n    }","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-core/src/data/dataloader/multithread.rs#L237-L273","documentation":"During Dataloader iteration, the main thread sends commands to worker threads over channels; the expect fires when a worker's channel sender is disconnected, meaning that worker thread has already terminated. The library assumes all workers stay alive for the iterator's lifetime, so a dead worker is an invariant violation.","triggerScenarios":"Calling iter() on a multi-threaded Dataloader after a worker thread panicked (e.g. its map/collate closure panicked) or was killed, so command_sender.send() fails because the receiver was dropped.","commonSituations":"User-supplied transforms/bug in dataset items that panic inside a worker; OOM killer terminating a worker thread; stopping the dataloader and re-iterating a workers handle in an inconsistent state.","solutions":["Fix the panic inside the worker (usually in the dataset indexing or collation closure) — check logs for the original worker panic message.","Recreate the Dataloader instead of reusing it after a worker failure.","Reduce memory pressure (smaller batch size, fewer workers) if workers were killed by OOM."],"exampleFix":"// before: dataset closure that can panic inside worker\nlet ds = Mapper::new(base, |item| item.parse().unwrap());\n// after\nlet ds = Mapper::new(base, |item| item.parse().unwrap_or_default());","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Wrap dataloader iteration and recreate on worker death\nmatch std::panic::catch_unwind(AssertUnwindSafe(|| {\n    for batch in dataloader.iter() { /* consume */ }\n})) {\n    Ok(_) => {},\n    Err(_) => dataloader = build_dataloader(); // workers died; rebuild\n}","preventionTips":["Avoid panicking operations (unwrap, direct indexing) in dataset/mapper closures","Monitor worker memory; reduce num_workers if OOM kills threads","Rebuild dataloaders rather than reusing them after errors"],"tags":["rust","dataloader","thread-panic","panic"],"backgroundTag":"worker-thread-died","analyzedSha":"d16f7ba2ed0d41408189384044cc886fb4c8f957","analyzedAt":"2026-09-05T13:19:14.260Z","contentChangedAt":"2026-09-05T13:19:14.260Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}