Skip to content

numfmt panics (aborts) on output write errors instead of reporting them #12551

@leeewee

Description

@leeewee

Summary

numfmt calls .unwrap() on every write to stdout. When a write to the output fails for any reason other than a broken pipe (e.g. the output device is full, or the output file/redirect is no longer writable), the unwrap() turns the io::Error into a panic. Because the release profile builds with panic = "abort", the process aborts (SIGABRT, exit 134, core dumped) instead of printing a clean diagnostic and exiting with a normal error status.

GNU numfmt handles the same situation gracefully: it prints numfmt: write error: ... and exits with status 1.

Steps to reproduce

The simplest trigger is writing to /dev/full (every write fails with ENOSPC):

$ numfmt 1024 > /dev/full
thread 'main' panicked at src/uu/numfmt/src/format.rs:872:34:
called `Result::unwrap()` on an `Err` value: Os { code: 28, kind: StorageFull, message: "No space left on device" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Aborted (core dumped)
$ echo $?
134

Any output write failure reaches the same problem through one of several code paths (plain numbers, -d/delimited input, --padding, unselected fields, etc.).

Expected behavior

Match GNU: report the write error and exit non-zero, without panicking.

$ /usr/bin/numfmt 1024 > /dev/full
/usr/bin/numfmt: write error: No space left on device
$ echo $?
1

Actual behavior

The process panics and aborts (exit 134), emitting a Rust panic message and a core dump instead of a user-facing error.

Note: the common numfmt ... | head broken-pipe case is not affected — there the process is terminated by SIGPIPE as expected. This report is specifically about non-pipe write failures (full disk, closed/failed redirect target, etc.).

Root cause

The output helpers in src/uu/numfmt/src/format.rs unwrap their writes rather than propagating the error. There are ~10 writer.write_all(...).unwrap() calls across write_formatted_with_delimiter and write_formatted_with_whitespace, e.g.:

writer.write_all(formatted.as_bytes()).unwrap();
...
writer.write_all(&[eol]).unwrap();

Environment

  • uutils coreutils: numfmt (uutils coreutils) 0.8.0 (commit aaf4a35, 2026-05-27)
  • rustc: 1.89.0
  • Reference: GNU coreutils 8.30

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions