uutils/coreutils · warning · io::Error

head-error-writing-stdout

Error message

head-error-writing-stdout

What it means

head wraps any I/O error that occurs while writing output to stdout with this 'error writing stdout' message, preserving the original error kind and appending the stripped errno text. It distinguishes failures on the output side (broken pipe, full disk) from failures reading the input files.

Source

Thrown at src/uu/head/src/head.rs:209

        options.verbose = matches.get_flag(options::VERBOSE);
        options.line_ending = LineEnding::from_zero_flag(matches.get_flag(options::ZERO));
        options.presume_input_pipe = matches.get_flag(options::PRESUME_INPUT_PIPE);

        options.mode = Mode::from(matches)?;
        // #[allow(clippy::unwrap_used, reason = "clap provides '-' by default")] <https://github.com/rust-lang/rust/issues/15701>
        options.files = matches
            .get_many::<OsString>(options::FILES)
            .unwrap()
            .cloned()
            .collect();

        Ok(options)
    }
}

#[inline]
fn wrap_in_stdout_error(err: io::Error) -> io::Error {
    io::Error::new(
        err.kind(),
        translate!("head-error-writing-stdout", "err" => uucore::error::strip_errno(&err)),
    )
}

// zero-copy fast-path
#[cfg(any(target_os = "linux", target_os = "android"))]
fn print_n_bytes(input: impl AsFd, n: u64) -> io::Result<u64> {
    let out = io::stdout();
    uucore::pipes::send_n_bytes(input, &out, n).map_err(wrap_in_stdout_error)
}

#[cfg(not(any(target_os = "linux", target_os = "android")))]
fn print_n_bytes(input: impl Read, n: u64) -> io::Result<u64> {
    // Read the first `n` bytes from the `input` reader.
    let mut reader = input.take(n);

    // Write those bytes to `stdout`.

View on GitHub (pinned to 325183372a)

Solutions

  1. Ignore it if caused by a downstream `head`/`q` closing the pipe — this is expected SIGPIPE/EPIPE behavior; ensure your script tolerates non-zero exit
  2. Check available space with `df` if stdout is redirected to a file and free space on the target filesystem
  3. Verify the consuming process in the pipeline is still alive and reads the data
  4. Handle SIGPIPE in the surrounding shell script (set -o pipefail considerations)

Example fix

// before
head -n 1000 huge.log > /mnt/full-disk/out.txt
// after
df -h /mnt/full-disk   # ensure space first
head -n 1000 huge.log > /mnt/full-disk/out.txt || echo "stdout write failed: $?"
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

// treat EPIPE on stdout as benign in pipelines
head -n 100 huge.log | head -n 5
if [ ${PIPESTATUS[0]} -ne 0 ]; then
  case $(head -n 100 huge.log 2>&1 >/dev/null) in
    *"error writing stdout"*) echo "benign broken pipe" ;;
  esac
fi

Prevention

When it happens

Trigger: head writes lines/bytes to stdout and the write fails — typically EPIPE when stdout is piped into a consumer that exits early (e.g., `head big | head -1` chains), or ENOSPC when stdout is redirected to a full disk/device.

Common situations: Piping head into commands like `less` then quitting, `| head` in scripts where downstream commands close the pipe, redirecting output to a full filesystem or a closed socket.

Related errors


AI-assisted analysis of uutils/coreutils@325183372a (2026-08-31). Data as JSON: /api/errors/cdc00921cc789ffd. Report an issue: GitHub.