Common Standard Macros

eprintln!

The eprintln! macro (along with its no-newline companion eprint!) writes formatted diagnostic, warning, or error messages to the process's standard error stream (stderr, file descriptor 2) instead of standard output (stdout, file descriptor 1).

Why Diagnostic Output Belongs on stderr

In command-line tools and Unix pipelines, separating data output (stdout) from human diagnostics (stderr) prevents warnings, progress bars, or error messages from corrupting piped or redirected structured output:

$ my_tool --input data.csv > results.json
                           │
  ├── println!("{json}")  ─┴─> Redirected into `results.json` (fd 1: stdout)
  └── eprintln!("WARN..") ───> Printed on user's terminal screen (fd 2: stderr)
Macro Target Stream File Descriptor Buffering Typical Use Case
println! / print! io::stdout() 1 Line-buffered (TTY) or block-buffered (pipe/file) Program output, JSON/CSV data, requested results
eprintln! / eprint! io::stderr() 2 Unbuffered / direct Errors, warnings, progress logs, debug traces

Reporting Errors and Warnings to stderr

fn parse_config_port(raw: &str) -> u16 {
    match raw.parse::<u16>() {
        Ok(port) => port,
        Err(err) => {
            eprintln!("warning: invalid port '{raw}' ({err}); falling back to 8080");
            8080
        }
    }
}

fn main() {
    let port = parse_config_port("not_a_number");
    // Data output goes to stdout:
    println!("{{\"port\": {port}}}");
}
warning: invalid port 'not_a_number' (invalid digit found in string); falling back to 8080
{"port": 8080}

Exiting with a Non-Zero Status Code After eprintln!

In CLI binaries, fatal user-facing errors are printed with eprintln! followed by std::process::exit(1) (or by returning std::process::ExitCode::FAILURE from main()):

use std::process::ExitCode;

fn run_app(args: &[&str]) -> Result<(), &'static str> {
    if args.is_empty() {
        return Err("missing required <input_file> argument");
    }
    println!("Processing {}", args[0]);
    Ok(())
}

fn main() -> ExitCode {
    if let Err(msg) = run_app(&["dataset.parquet"]) {
        eprintln!("error: {msg}");
        return ExitCode::FAILURE;
    }
    ExitCode::SUCCESS
}
Processing dataset.parquet