{"record":{"id":"44865da8522b8663","repo":"stamparm/maltrail","slug":"capture-error-on-worker-e","errorCode":null,"errorMessage":"capture error on worker {} ({e})","messagePattern":"capture error on worker (.+?) \\((.+?)\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sensor/src/worker.rs","lineNumber":225,"sourceCode":"                                handle = next;\n                                label = next_label;\n                                file_started = Instant::now();\n                                file_packets = 0;\n                                file_events = st.sink.events;\n                                datalink = handle.datalink();\n                                poll_fd = handle.selectable_fd();\n                                continue;\n                            }\n                            None => {\n                                outcome = Ok(WorkerExit::OfflineEof);\n                                fatal = true;\n                            }\n                        }\n                    }\n                    break;\n                }\n                Err(e) => {\n                    crate::output::log_error(&format!(\"capture error on worker {} ({e})\", ctx.id), true);\n                    if offline {\n                        // A capture error is NOT a clean end of file. If it happened before a\n                        // single packet was read, the capture could not be read at all, and\n                        // reporting a successful replay of zero packets is the offline version\n                        // of the silent blind spot Gate 1.1 fixed: the analyst sees \"no\n                        // detections\" when the truth is \"your file was never parsed\".\n                        //\n                        // Found by the shadow harness on a `mergecap` output — libpcap refuses a\n                        // pcapng whose interfaces have different link types, and the sensor\n                        // replayed it to \"success\" with received=0.\n                        //\n                        // After packets HAVE been read this is a truncated tail: the events found\n                        // so far are real and worth keeping, so the run still succeeds and the\n                        // error stands in the log.\n                        if st.metrics.packets_received == 0 {\n                            outcome = Err(WorkerError::Capture(format!(\"{e} (no packets could be read)\")));\n                        } else {\n                            outcome = Ok(WorkerExit::OfflineEof);","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/stamparm/maltrail/blob/77cfb06d7606506d101bbcec0786c77166c4255e/sensor/src/worker.rs#L207-L243","documentation":"This error is logged when the libpcap packet-capture read call inside the worker loop returns Err(e). In offline (pcap file replay) mode it means the capture file could not be read at all (or hit a malformed/truncated region); if zero packets were read the worker fails with WorkerError::Capture instead of silently reporting a successful replay of zero packets. In live-capture mode it means the capture handle hit an error (e.g. interface disappeared); only after LIVE_CAPTURE_ERROR_LIMIT consecutive errors does it become fatal.","triggerScenarios":"Calling run_all/run with an offline pcap/pcapng file that libpcap cannot read — e.g. a mergecap pcapng whose interfaces have different link types — or a truncated/corrupt capture file; or a live capture whose interface errors out (device gone, permission/privilege loss, BPF/capture handle failure).","commonSituations":"Replaying a mergecap-produced pcapng with mismatched per-interface link types; a capture file cut off mid-write (truncated tail after some packets); running a live capture and the NIC is removed or link state changes; insufficient privileges causing the capture handle to degrade.","solutions":["Validate the capture file with tshark -r file or capinfos before replaying; fix the source file (e.g. re-merge with mergecap -F pcap so all interfaces share one link type).","Check the log for '(no packets could be read)': if absent, packets were already processed and the error is only a truncated tail — treat the run's events as valid.","For live captures, verify interface name and permissions (capabilities/root, or configure the ambient-capture capability); the failure becomes fatal only after repeated consecutive errors, so check whether LIVE_CAPTURE_ERROR_LIMIT was hit.","Ensure the pcapng was written completely before replay; use the final, non-growing file."],"exampleFix":"// before\nsensor replay merged.pcapng   # exits 0, received=0, 'capture error on worker 0'\n// after\nmergecap -w merged.pcap merged1.pcapng merged2.pcapng  # single link type / pcap format\nsensor replay merged.pcap    # packets parsed, events produced","handlingStrategy":"validation","validationCode":"import subprocess, sys\ndef validate_capture(path: str) -> bool:\n    \"\"\"Ensure libpcap/tshark can read the capture before replaying.\"\"\"\n    r = subprocess.run([\"capinfos\", path], capture_output=True, text=True)\n    if r.returncode != 0:\n        print(f\"unreadable capture: {r.stderr}\", file=sys.stderr)\n        return False\n    if int(r.stdout.split('Number of packets:')[1].split()[0]) == 0:\n        print('capture has zero packets', file=sys.stderr)\n        return False\n    return True\n\nassert validate_capture('merged.pcapng'), 'fix capture file before replay'","typeGuard":"fn is_readable_capture(path: &str) -> bool {\n    pcap::Capture::from_file(path)\n        .map(|mut c| c.next_packet().is_ok())\n        .unwrap_or(false)\n}","tryCatchPattern":"match sensor.run_all() {\n    Ok(report) if report.received > 0 => { /* success */ }\n    Ok(report) => eprintln!(\"replay succeeded but 0 packets read — check capture file\"),\n    Err(sensor::Error::Capture(msg)) => eprintln!(\"capture failed: {msg}\"),\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Run capinfos/tshark -r on capture files before feeding them to the sensor","Use mergecap with an explicit format (-F pcap) so all interfaces share one link type","Never replay a capture file still being written (truncated tails)","Verify interface permissions and link state before starting live capture","Monitor for 'capture error on worker' log lines; treat zero-packet successful runs as a red flag"],"tags":["pcap","libpcap","packet-capture","offline-replay","truncated-capture"],"backgroundTag":"file-read-failed","analyzedSha":"77cfb06d7606506d101bbcec0786c77166c4255e","analyzedAt":"2026-09-13T03:50:16.010Z","contentChangedAt":"2026-09-13T03:50:16.010Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}