{"record":{"id":"102f298c17dc0d72","repo":"imsnif/bandwhich","slug":"failed-to-write-to-stdout-e","errorCode":null,"errorMessage":"Failed to write to stdout: {e}","messagePattern":"Failed to write to stdout: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/os/shared.rs","lineNumber":103,"sourceCode":"}\n\nfn get_interface(interface_name: &str) -> Option<NetworkInterface> {\n    datalink::interfaces()\n        .into_iter()\n        .find(|iface| iface.name == interface_name)\n}\n\nfn create_write_to_stdout() -> Box<dyn FnMut(&str) + Send> {\n    let mut stdout = io::stdout();\n    Box::new({\n        move |output| match writeln!(stdout, \"{output}\") {\n            Ok(_) => (),\n            Err(e) if e.kind() == ErrorKind::BrokenPipe => {\n                // A process that was listening to bandwhich stdout has exited\n                // We can't do much here, lets just exit as well\n                std::process::exit(0)\n            }\n            Err(e) => panic!(\"Failed to write to stdout: {e}\"),\n        }\n    })\n}\n\npub fn get_input(\n    interface_name: Option<&str>,\n    resolve: bool,\n    dns_server: Option<Ipv4Addr>,\n) -> eyre::Result<OsInputOutput> {\n    // get the user's requested interface, if any\n    // IDEA: allow requesting multiple interfaces\n    let requested_interfaces = interface_name\n        .map(|name| get_interface(name).ok_or_else(|| eyre!(\"Cannot find interface {name}\")))\n        .transpose()?\n        .map(|interface| vec![interface]);\n\n    // take the user's requested interfaces (or all interfaces), and filter for up ones\n    let available_interfaces = requested_interfaces","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/imsnif/bandwhich/blob/1899870cea8bb377948f05cfea64733ec6ea2cd6/src/os/shared.rs#L85-L121","documentation":"bandwhich writes its report snapshots to stdout from a dedicated thread. If a write to stdout fails and it is not a benign BrokenPipe (consumer exited), the code panics with this message rather than continuing with a broken output stream.","triggerScenarios":"Calling `create_write_to_stdout`'s spawned write task when stdout is closed, redirected to a failing file/pipe with a non-broken-pipe error (e.g. ENOSPC, EPIPE variant with different kind, EIO on a detached terminal), or the receiver ends of `stdout_write` are dropped.","commonSituations":"Piping bandwhich into a process that dies mid-run without a clean SIGPIPE, running with stdout redirected to a full disk, running under a supervisor that closes stdout, or running in environments (CI, systemd) where stdout is detached.","solutions":["Ensure the consumer of bandwhich stdout (e.g. `bandwhich --raw | consumer`) stays alive and reads stdout continuously","Check disk space / filesystem health if stdout is redirected to a file","Run bandwhich in a terminal or with a valid pipe, not with a closed stdout (`bandwhich >&-`)","If piping programmatically, handle BrokenPipe as normal shutdown and treat other io::Error kinds as fatal"],"exampleFix":"// before\nbandwhich | grep -m1 eth0\n// after\nbandwhich --raw | while read line; do grep -m1 eth0 <<< \"$line\" && break; done; # keep reader alive until match","handlingStrategy":"try-catch","validationCode":"// Rust (caller): only pipe when a live reader exists\nuse std::io::IsTerminal;\nlet safe = std::io::stdout().is_terminal() || reader_is_alive();\nif !safe { eprintln!(\"stdout has no live reader; use --raw with a consuming pipe\"); }","typeGuard":"fn stdout_is_writable() -> bool {\n    use std::io::Write;\n    let mut out = std::io::stdout();\n    out.write_all(b\"\").is_ok()\n}","tryCatchPattern":"match stdout.write_all(&bytes) {\n    Ok(_) => {}\n    Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => std::process::exit(0),\n    Err(e) => eprintln!(\"stdout write failed: {e}\"), // log & exit cleanly instead of panicking\n}","preventionTips":["Always pipe bandwhich --raw into a process that consumes stdout until bandwhich exits","Avoid redirecting stdout to files on full/disks or closed descriptors (`>&-`)","Treat BrokenPipe as graceful shutdown, as bandwhich does","Monitor disk space when redirecting output"],"tags":["rust","stdout","io"],"backgroundTag":"file-write-failed","analyzedSha":"1899870cea8bb377948f05cfea64733ec6ea2cd6","analyzedAt":"2026-09-08T10:26:38.858Z","contentChangedAt":"2026-09-08T10:26:38.858Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}