Skip to content
Select theme

How to print to standard error

Short answer: eprintln! is println! writing to standard error — same format string, different stream. Keep the program’s real output on stdout and everything else on stderr, and every pipe (prog | grep) and redirect (prog > out.txt) receives only the real output.

From a fresh project — cargo new stderr-demo, then replace src/main.rs with each block below and run it with cargo run. The project name doesn’t matter until the shell commands further down — the binary is named after it.

results.txt
scanning directory

In a terminal both lines appear, in the order the program writes them. They are not on the same stream, though, and the shell can separate them. Drop standard error and only the data is left:

Terminal window
./target/debug/stderr-demo 2>/dev/null
results.txt

Drop standard output and only the diagnostics are left:

Terminal window
./target/debug/stderr-demo 1>/dev/null
scanning directory

The binary takes the project’s name — with stderr-demo it sits at target/debug/stderr-demo. Run cargo build first, or use cargo run --quiet with the same redirects.

That split is what makes a chatty program safe to pipe. The answers go to stdout, the talking goes to stderr:

Now the shell can filter the answers without filtering the talk:

Terminal window
./target/debug/stderr-demo | wc -l
2
Terminal window
./target/debug/stderr-demo | grep beta
beta.txt

wc counted two lines because a pipe carries stdout only; the progress lines went to the terminal instead. prog | grep pattern and prog > results.txt stay usable no matter how much the program talks. Capture the talking rather than losing it with 2>progress.txt, then read the file when something looks wrong. cargo run | wc -l works the same way — cargo’s own Finished and Running lines sit on stderr, which is why they never reach the pipe.

eprint! is the no-newline variant, and it needs no flush: standard error is unbuffered, so every write goes straight out. Redirect it to a file and half a second in the text is already there — the buffer that holds print! back does not exist here. The format string is the same one every print macro takes, inline captures included.

One failure mode: eprintln! panics if the write fails, exactly as print! does. Pipe standard error into head and when head stops reading, the program dies with exit code 101.