{"record":{"id":"5643d8194d446411","repo":"AlexsJones/llmfit","slug":"csv-flush-failed","errorCode":null,"errorMessage":"CSV flush failed","messagePattern":"CSV flush failed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"llmfit-tui/src/display.rs","lineNumber":1042,"sourceCode":"                score_fit: round1(fit.score_components.fit),\n                score_context: round1(fit.score_components.context),\n                estimated_tps: round1(fit.estimated_tps),\n                memory_required_gb: round2(fit.memory_required_gb),\n                memory_available_gb: round2(fit.memory_available_gb),\n                utilization_pct: round1(fit.utilization_pct),\n                disk_size_gb: round2(fit.model.estimate_disk_gb(&fit.best_quant)),\n                best_quant: fit.best_quant.clone(),\n                runtime: fit.runtime.label().to_string(),\n                use_case: fit.use_case.label().to_string(),\n                release_date: fit.model.release_date.clone(),\n                license: fit.model.license.clone(),\n                is_moe: fit.model.is_moe,\n                installed: fit.installed,\n            })\n            .expect(\"CSV serialization failed\");\n    }\n\n    writer.flush().expect(\"CSV flush failed\");\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use llmfit_core::fit::{FitLevel, InferenceRuntime, ScoreComponents};\n    use llmfit_core::models::{Capability, GgufSource, ModelFormat, UseCase};\n\n    fn mock_fit(run_mode: RunMode, use_case: UseCase, model_use_case: &str) -> ModelFit {\n        ModelFit {\n            model: LlmModel {\n                name: \"test/model-7b\".to_string(),\n                provider: \"test\".to_string(),\n                parameter_count: \"7B\".to_string(),\n                parameters_raw: None,\n                min_ram_gb: 4.0,\n                recommended_ram_gb: 8.0,\n                min_vram_gb: Some(4.0),","sourceCodeStart":1024,"sourceCodeEnd":1060,"githubUrl":"https://github.com/AlexsJones/llmfit/blob/8f16394d7478d03a12937d50eec41b39311052d8/llmfit-tui/src/display.rs#L1024-L1060","documentation":"Panic from .expect(\"CSV flush failed\") on writer.flush() at the end of display_csv_fits (display.rs:991). The csv::Writer wraps std::io::stdout(), and flush pushes buffered rows through std::io::Stdout::flush — it fails with an IO error when the pipe is already broken (downstream consumer exited), when stdout is redirected to a full disk (ENOSPC), or when the target file/mount disappears mid-run. Since SIGPIPE is ignored in Rust programs, a reader closing the pipe early shows up here as a flush error rather than a signal.","triggerScenarios":"The final flush after `llmfit fit --csv | head -n1` (head exits after one line, stdout breaks); redirecting to a file on a filesystem that fills up between row writes and flush; piping into a subprocess that crashes partway.","commonSituations":"Automation sampling large CSV outputs; cron jobs writing CSV to nearly-full volumes; interactive use with pagers quit early; NFS/FUSE mounts that drop during long outputs.","solutions":["Write to a file first (`llmfit fit --csv > out.csv`) and post-process the file — this eliminates broken pipes entirely.","Verify free space on the redirection target (df -h .) and on $TMPDIR when piping through tools like sponge/tee.","Ensure the downstream pipe consumer reads until EOF instead of exiting early, or drop the pipe.","As a maintainer, treat BrokenPipe on flush as success (exit 141 silently) and surface other IO errors on stderr instead of expect."],"exampleFix":"// before\nwriter.flush().expect(\"CSV flush failed\");\n\n// after\nif let Err(e) = writer.flush() {\n    if e.kind() == std::io::ErrorKind::BrokenPipe {\n        std::process::exit(141);\n    }\n    eprintln!(\"error: failed to flush CSV output: {e}\");\n    std::process::exit(1);\n}","handlingStrategy":"fallback","validationCode":"# Shell-level: ensure the flush has somewhere to go and the target is writable.\nllmfit fit --csv > /tmp/llmfit-models.csv || echo \"csv write failed (disk full?)\" >&2\ntest -s /tmp/llmfit-models.csv   # confirm non-empty output landed","typeGuard":null,"tryCatchPattern":"let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    display::display_csv_fits(&fits);\n}));\nif result.is_err() {\n    eprintln!(\"error: CSV flush failed (downstream reader closed early or disk full)\");\n    std::process::exit(141);\n}","preventionTips":["Redirect CSV output to a local file rather than piping or writing to network mounts.","Monitor disk usage on volumes that receive redirected output, especially after model downloads.","Let downstream consumers read to EOF; if sampling is required, sample the file afterwards.","Maintainers: handle BrokenPipe on flush as a clean exit, not a panic."],"tags":["rust","csv","broken-pipe","stdout-flush","panic"],"backgroundTag":"broken-pipe","analyzedSha":"8f16394d7478d03a12937d50eec41b39311052d8","analyzedAt":"2026-08-17T10:35:29.658Z","contentChangedAt":"2026-08-17T10:35:29.658Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}