{"record":{"id":"644041b2cf0caf9c","repo":"stamparm/maltrail","slug":"short-write-to-the-event-log-n-of-bytes-the-record-may-be","errorCode":null,"errorMessage":"short write to the event log ({n} of {} bytes); the record may be truncated","messagePattern":"short write to the event log \\((.+?) of (.+?) bytes\\); the record may be truncated","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sensor/src/output.rs","lineNumber":367,"sourceCode":"        }\n        if let Some(file) = self.log_file.as_mut() {\n            // ONE write(2) per event, deliberately — not `write_all`.\n            //\n            // The guarantee that matters with several workers appending to one file is that each\n            // event line lands whole: O_APPEND makes the kernel pick the append offset and perform\n            // the copy atomically *per system call*, so one call per line means workers interleave\n            // whole records. `write_all` loops on a short write, which would split a line across\n            // two calls and let another worker's line land in the middle of it.\n            //\n            // (An earlier comment here justified this with PIPE_BUF. That was wrong: PIPE_BUF\n            // bounds atomic writes to PIPES, not regular files. The property being relied on is\n            // O_APPEND's atomic offset-plus-write, which has no such size bound in practice but is\n            // also not unlimited — hence treating a short write as an error rather than looping.)\n            match file.write(line.as_bytes()) {\n                Ok(n) if n == line.len() => {}\n                Ok(n) => {\n                    self.log_write_errors += 1;\n                    log_error(\n                        &format!(\n                            \"short write to the event log ({n} of {} bytes); the record may be truncated\",\n                            line.len()\n                        ),\n                        true,\n                    )\n                }\n                Err(e) => {\n                    self.log_write_errors += 1;\n                    log_error(&format!(\"unable to write event log ({e})\"), true)\n                }\n            }\n        }\n    }\n\n    /// Matched against \"<info> <reference>\". Whether a verdict was corroborated lives in the\n    /// reference, and REMOTE_SEVERITY_REGEX has to see it to rank a heuristic guess below a feed\n    /// hit the way the dashboard does - `core/log.py:severity_of()` does the same.","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/stamparm/maltrail/blob/77cfb06d7606506d101bbcec0786c77166c4255e/sensor/src/output.rs#L349-L385","documentation":"A write to the event log wrote fewer bytes than the serialized event line, meaning the record may be truncated on disk. The code performs a single write(2) per event (relying on O_APPEND atomicity) and deliberately treats a short write as an error instead of looping, because the append size bound makes partial writes abnormal.","triggerScenarios":"file.write(line.as_bytes()) returns Ok(n) where n < line.len() during write_event_log. Typically only when the write exceeds the pipe/append size bound or the disk fills mid-write.","commonSituations":"Very large event lines combined with a full or nearly full filesystem; writes to a log on a pipe/special file rather than a regular file; kernel resource pressure interrupting large writes.","solutions":["Check disk space on the event log filesystem (df -h) and free space or rotate the log.","Ensure the event log path is a regular file on local storage, not a pipe or network mount.","Reduce event line size (payload truncation settings) if events are extremely large.","Treat affected records as suspect: inspect the log tail and re-verify events around the error timestamp."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// ensure the log target is a regular file on a filesystem with headroom\nlet md = std::fs::metadata(log_path)?;\nif !md.is_file() { eprintln!(\"event log must be a regular file\"); }\nlet free = fs4::available_space(log_path)?;\nif free < 64 * 1024 * 1024 { eprintln!(\"low disk space for event log\"); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep headroom on the event log filesystem and rotate logs proactively","Keep event line sizes bounded (payload truncation settings)","Avoid pointing the event log at pipes or network filesystems","Watch for short-write log lines and investigate immediately"],"tags":["file-io","short-write","truncation","logging"],"backgroundTag":"file-write-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"}