When to use standard error stream in command-line application?

Yes, do display a message on stderr when the wrong arguments are used. And if that also causes the application to exit, exit with non-zero exit status.

You should use the standard error stream for diagnostic messages or for user interaction. Diagnostic messages include error messages, warnings and other messages that are not part of the utility's output when it's operating correctly ("correctly" meaning there is nothing exceptional happening, like files not being found, or whatever it may be).

Many shells (all?) display prompts, what the user types, and menus etc. on stderr so that redirecting stdout won't stop you from interacting with the shell in a meaningful way.

The following is from a blog post on this topic:

This is a quote from Doug McIllroy, inventor of Unix pipes, explaining how stderr came to be. 'v6' is referring to a version of specific version of the original Unix operating system that was released in 1975.

All programs placed diagnostics on the standard output. This had always caused trouble when the output was redirected into a file, but became intolerable when the output was sent to an unsuspecting process. Nevertheless, unwilling to violate the simplicity of the standard-input-standard-output model, people tolerated this state of affairs through v6. Shortly thereafter Dennis Ritchie cut the Gordian knot by introducing the standard error file. That was not quite enough. With pipelines diagnostics could come from any of several programs running simultaneously. Diagnostics needed to identify themselves.
-- Doug McIllroy, "A Research UNIX Reader: Annotated Excerpts from the Programmer’s Manual, 1971-1986"

To "identify oneself" means simply saying "Hey! It's me talking! This went wrong: [...]":

$ ls nothere
ls: nothere: No such file or directory

Doing this on stderr is preferable, since it could otherwise be read by whatever was reading on stdout (but we don't do that with ls anyway, do we?).


From POSIX specifications for the standard streams:

At program start-up, three streams shall be predefined and need not be opened explicitly: standard input (for reading conventional input), standard output (for writing conventional output), and standard error (for writing diagnostic output).

In other words, errors, debugging info, and anything that falls into diagnostic category goes into stderr.

See related question for more info: Do progress reports/logging information belong on stderr or stdout?