Also available in: Español · Português · Français · العربية
Exit codes explained
Look up a Unix exit status and see every reading it can carry — and, for each one, which document actually says so.
What is an exit code?
When a program finishes, it hands the system a single number between 0 and 255. Zero means it succeeded. Anything else means it did not, and that is very nearly the whole of what is guaranteed. The shell keeps that number in the variable written as a question mark, CI systems print it when a step fails, and container runtimes report it when something stops.
Almost every exit code table on the web presents one flat list — 0 success, 1 general error, 2 misuse of builtins, 64 to 78 from sysexits, 126, 127, 128 plus the signal number — as though a single standard said all of it. Reading the actual documents, those rows come from four different places, and one of the most-quoted comes from nowhere at all. This page decodes a status and tells you, for each reading, which document is behind it.
That distinction is not pedantry. It is the difference between a rule you can rely on another program obeying and a habit that happens to be common in the corner of the world you learned it in.
How to use it
- Type the number. Whatever your CI log, container runtime or shell reported. The buttons cover the ones people most often arrive with.
- Read every reading, not just the first. One number can be several things at once — 64 is both a sysexits code and an ordinary number a program picked for its own reasons, and showing only one of those would be a claim the sources do not support.
- Check who defines it. Each reading is labelled POSIX, Bash manual, sysexits.h, or no standard. That label is the part worth remembering.
Which numbers are actually specified
POSIX, in the Shell Command Language, fixes very little: zero for success, 127 when a command is not found, and 126 when it is found but cannot be run. Those three are worth trusting anywhere. For a program killed by a signal it says only that the status shall be greater than 128 and shall identify the signal in an implementation-defined manner — it does not say 128 plus the signal number.
That last part surprises people, because 128 plus the signal number is exactly what happens. It is in the Bash manual rather than in POSIX: bash states that when a command terminates on a fatal signal N, it uses 128+N. Measured here across bash, dash and the system shell, all three agreed: a process killed by SIGTERM reported 143, by SIGKILL 137, by SIGINT 130, by SIGHUP 129. It is thoroughly reliable in practice and it is a shell's promise, not the standard's.
Bash also defines 2, but far more narrowly than the tables suggest: all its builtins return 2 to indicate incorrect usage, such as an invalid option or a missing argument. That is a fact about bash's own builtins. It is not advice about what your script should return, and nothing obliges any other program to follow it.
And then there is 1, the most tabulated exit code on the internet, universally captioned general error. No document defines it. POSIX and the Bash manual both say only that a non-zero status indicates failure. Counted across all 256 possible values, some document says something about 50 of them; the other 206 are left entirely to the program.
Two things the tables get wrong
The first is sysexits. The codes from 64 to 78 are presented everywhere as the standard exit codes, and they were never part of POSIX. They come from a C header written for sendmail, and the header is unusually frank about itself: it says the values exist only for interface compatibility and are deprecated for FreeBSD base software, that they were written for notably sendmail, and — before listing them — that the meaning of the codes is approximately as follows. A set of constants whose own author describes their meanings as approximate is a reasonable convention to follow inside a project that already uses it, and a poor thing to expect a stranger's program to honour.
The second is that 128 plus a signal number does not always identify a signal. Getting from the status back to the signal requires knowing which signal has that number, and signal numbers are not the same everywhere. On x86 Linux signal 10 is SIGUSR1; on Alpha, SPARC and macOS it is SIGBUS. So exit status 138 means a user-defined signal on one machine and a bus error on another, and no table that prints a single name for it can be right on both. Type 138 above and the tool shows you the split rather than picking one.
There is a smaller trap in the other direction. A status is eight bits, so returning something larger silently wraps: exit 256 arrives as 0, which turns a failure into a success. Measured here, exit 300 came back as 44 and exit 257 as 1. Negative numbers are worse than merely wrapped — bash turned -1 into 255, while dash refused it outright with an illegal number message and returned 2, so the same script reports two different failures depending on which shell ran it.
Why non-zero does not mean broken
The convention everybody carries around is that zero is fine and anything else is a problem. The two utilities most likely to appear in a shell pipeline both contradict it. grep returns 1 when it simply found no matches, and reserves 2 for an actual error. diff returns 1 when the files differ, which is the normal answer to the question it was asked, and also reserves 2. cmp does the same.
This is the practical reason the caveat at the bottom of every result on this page matters. A script running under set -e will stop on a grep that found nothing, because the shell cannot tell the difference between an answer of no and a failure — both are 1. Knowing which of your tools use 1 as an answer rather than an error is more useful than any table of standard codes, because it is the case that actually bites.
If you are choosing codes for your own program: zero for success, non-zero for failure, and document what each number means. That is the whole of the portable contract. If you want more structure than that, pick a scheme and write it down, because the reader of your exit status has no way to look it up.
Why is it free?
This is a lookup table and some arithmetic, running in your browser. There is nothing to run on a server, so there is nothing to charge for and no account to create.
Nothing you type is uploaded, stored or logged — and there is not much to log, since the input is a number between 0 and 255.