208 of 208 codes
The operation requires privileges that the process does not have, such as changing the owner of a file, sending a signal to another user's process or modifying an immutable file (chattr +i). Unlike EACCES, it is not solved by changing the file's permissions: it takes root or the corresponding capability.
The file or directory does not exist. It also appears when an intermediate directory in the path is missing, when a symbolic link points to a target that does not exist or when the interpreter in a script's #! line is not installed.
No process, process group or thread exists with that ID; for example, when running kill on a PID that has already exited.
A signal interrupted the system call before it finished. It is not a real error: the program should retry the call, or install the signal handler with SA_RESTART.
Low-level input/output error, usually when reading from or writing to the device. On disks it usually points to bad sectors or a faulty cable: check dmesg and the SMART status. It also appears when writing to a terminal that has already been closed.
The device or address does not exist: the device file is there, but there is no hardware behind it, or a FIFO was opened for writing with O_NONBLOCK without any reader.
The list of arguments and environment variables passed to exec is too large. It is the classic “Argument list too long” when using a wildcard that expands to thousands of files; use find -exec or xargs.
The file is not in a recognized executable format: it is a binary for another architecture, it is corrupted or it is a script without a #! line.
The file descriptor is not valid, has already been closed or was opened in a mode that does not allow the operation, such as writing to one opened read-only.
The process has no children to wait for with wait or waitpid, often because SIGCHLD is ignored and children are reaped automatically.
The resource is temporarily unavailable and it is worth retrying. In non-blocking operations it means that there is no data or space yet; in fork, that the process or thread limit has been reached (ulimit -u or the cgroup's pids.max).
Same value:EWOULDBLOCK
There is not enough memory for the operation or a process memory limit was exceeded. In fork or mmap it may be due to the overcommit policy, the cgroup limit or a lack of address space.
Permission denied by the permissions of the file or of a directory in the path (each one needs execute permission), by an ACL, by SELinux or AppArmor, or by a noexec mount. bind also returns it when using a port below 1024 without privileges.
A pointer to an invalid memory address was passed to a system call. It indicates a bug in the program.
The operation needs a block device, such as a disk, and received another type of file; for example, when mounting a regular file without -o loop.
The device or resource is busy. It is typical when unmounting a file system that has open files or a terminal located in it; lsof or fuser show which processes are using it.
A file, directory or other object with that name already exists, for example when creating with O_EXCL, when using mkdir without -p or when creating a link whose destination already exists.
A hard link cannot be created, nor a file renamed, across different file systems. mv handles it by copying and deleting; programs that use rename() must do the same.
The device does not exist or does not support the operation; for example, when mounting a file system type whose kernel module is not loaded.
A component of the path that should be a directory is a file, or a directory was requested (O_DIRECTORY) and it is not one.
A file operation was attempted on a directory, such as opening it for writing.
An argument is not valid for the call: a value out of range, an incompatible combination of options or an operation that the object does not support. It is generic: the call's man page lists the specific cases.
The system-wide open file table is exhausted. The limit is adjusted with fs.file-max in sysctl.
The process reached its limit of open descriptors (“Too many open files”). Raise the limit with ulimit -n or with LimitNOFILE in systemd, and check that the program is not leaving files or sockets unclosed.
A terminal operation (ioctl) was requested on something that is not a terminal, for example when the output of an interactive program is redirected to a file or a pipe.
The executable is in use: you cannot write to a binary while it is running, nor run one that is still open for writing. To update it, write a new file and rename it.
The file exceeds the maximum size supported by the file system (4 GB on FAT32) or the process's RLIMIT_FSIZE limit.
No space left on the device. If df shows free space, check the inodes with df -i. inotify also returns it when fs.inotify.max_user_watches is exhausted.
lseek cannot be used on a pipe, a FIFO or a socket, because they have no position.
The file system is mounted read-only. If it became read-only without anyone asking for it, the kernel did it after detecting errors: check dmesg and run fsck.
The maximum number of hard links to a file was exceeded or, on some file systems, the maximum number of subdirectories in a directory.
Data was written to a pipe or socket whose other end has already been closed (“Broken pipe”). Besides the error, the process receives SIGPIPE; it is normal when the reader exits first, as in cmd | head.
The argument of a math function is outside its domain, such as the square root of a negative number.
The result of a function is too large or too small to be represented, or a buffer is not big enough for the result, as in getcwd with a short buffer.
A deadlock was avoided: the requested lock, such as a file lock with fcntl or an error-checking mutex, would have waited forever.
Same value:EDEADLOCK
The path or one of its components exceeds the maximum length: on Linux, generally 255 bytes per name and 4096 per path.
No locks available. On NFS it usually means that the locking service (lockd or rpc.statd) is not running.
The system call does not exist in this kernel or is not implemented. It is typical of binaries built for a newer kernel, or of container seccomp profiles that do not know about recent calls.
The directory is not empty, for example when using rmdir or when renaming over an existing directory. To delete it along with its contents, use rm -r.
Too many symbolic links were chained while resolving the path, usually because of a loop, or O_NOFOLLOW was used on a symbolic link.
There is no message of the requested type in the System V message queue.
The System V IPC identifier (queue, semaphore or shared memory) was removed while the process was using it.
Channel number out of range. It is a legacy code with no practical use on Linux.
Level 2 not synchronized. It is a legacy System V code with no practical use on Linux.
Level 3 halted. It is a legacy System V code with no practical use on Linux.
Level 3 reset. It is a legacy System V code with no practical use on Linux.
Link number out of range. It is a legacy code with no practical use on Linux.
The protocol driver is not attached. Few subsystems use it, such as some Bluetooth drivers.
No CSI structure available. It is a legacy code with no practical use on Linux.
Level 2 halted. It is a legacy System V code with no practical use on Linux.
Invalid exchange. It is a legacy code that some drivers and file systems reuse with their own meaning.
Invalid request descriptor. It is a legacy code that some drivers reuse with their own meaning.
Exchange full. It is a legacy code with no practical use on Linux.
No “anode”. It is a legacy code with no practical use on Linux.
Invalid request code. It is legacy; some drivers use it for commands they do not support.
Invalid slot. It is a legacy code with no practical use on Linux.
Bad font file format. It is a legacy code with no practical use on Linux.
The device is not a STREAM. It belongs to the System V STREAMS interface, which Linux does not implement.
No data available. On Linux, getxattr returns it when the extended attribute does not exist; on macOS that case is ENOATTR.
A timer expired. It comes from STREAMS; on Linux some drivers and io_uring use it for operations with a timeout.
Out of STREAMS resources, an interface that Linux does not implement.
The machine is not on the network. It is a rarely used legacy code.
The package is not installed. It is legacy; some subsystems use it when a module is missing, for example a cryptographic one.
The object is remote. On NFS it indicates a path that is exported from another server.
The link has been severed. It is legacy; some drivers use it when the connection to the device is lost.
“Advertise” error. It is a legacy RFS code with no use on Linux.
“Srmount” error. It is a legacy RFS code with no use on Linux.
Communication error on send. It is legacy; some network and USB drivers use it.
Protocol error: the other end or the device responded with something unexpected. It appears with USB devices and on connections that drop in the middle of an exchange.
A multihop was attempted. It is a legacy RFS code.
RFS-specific error. Not used on Linux.
The message is malformed or corrupted. ext4, XFS and Btrfs return it, under the alias EFSBADCRC, when a metadata checksum fails.
Same value:EFSBADCRC
The value does not fit in the target data type; for example, a 32-bit program built without large file support that opens a file larger than 2 GB.
The name is not unique on the network. It is a legacy code.
The file descriptor is in a bad state. ALSA and some drivers use it when the device is not ready.
The remote address changed. It is a legacy code.
A required shared library cannot be accessed. It is a legacy code from a.out binaries.
The shared library is corrupted. It is a legacy code from a.out binaries.
The .lib section of the a.out binary is corrupted. It is a legacy code.
An attempt was made to link too many shared libraries. It is a legacy a.out code.
A shared library cannot be executed directly. It is a legacy a.out code.
The byte sequence is not valid for the character encoding, such as text that is not valid UTF-8 when converting it with iconv or with the multibyte functions.
The interrupted call should be restarted. It is for internal kernel use and should not reach programs.
STREAMS pipe error. ALSA returns it when the audio device is suspended.
Too many users. The disk quota system returns it when its table fills up, and it is uncommon.
A socket operation was used on a descriptor that is not a socket.
Destination address required: data was sent through a connectionless socket without specifying where to.
The message is too large for the socket, such as a UDP datagram larger than the maximum or than the MTU when fragmentation is not allowed.
The protocol does not match the socket type.
The requested socket option or protocol is not available, for example a setsockopt option that the kernel does not know.
The protocol is not supported, for example because its kernel module is not loaded.
The socket type is not supported in that address family.
The operation is not supported by the socket or the object. On Linux it has the same value as ENOTSUP, and many file systems return it for features they do not implement, such as fallocate or extended attributes.
The operation is not supported. On Linux it has the same value as EOPNOTSUPP (95); on macOS they are different codes.
The protocol family is not supported.
The address family is not supported; it is typical when using IPv6 on a system or container that has it disabled.
The address and port are already in use: another process is listening on that port, or the previous connection is still in TIME_WAIT. Find the process with ss -ltnp or lsof -i :PORT, or use SO_REUSEADDR.
The requested address cannot be assigned: the IP does not belong to any interface on the machine, or the ephemeral ports for outgoing connections have run out.
The network interface is down.
The destination network is unreachable because there is no route to it. Check the routing table and the gateway; it also happens when connecting over IPv6 without IPv6 connectivity.
The network reset the connection, for example when a keepalive fails.
The connection was aborted on the local side, for example because the client closed it before the server accepted it with accept.
The other end abruptly closed the connection with an RST (“Connection reset by peer”): the remote process shut down, a firewall or a load balancer cut the idle connection, or data was sent that the other side did not expect.
No kernel buffer space is available for the network operation; it usually appears under heavy traffic or when the socket queues are full.
The socket is already connected.
The socket is not connected: an attempt was made to send or receive before connecting, or the connection has already been closed. On a FUSE mount it appears as “Transport endpoint is not connected” when its process has died; it is fixed by unmounting with fusermount -u.
Cannot send after that direction of the socket has been closed with shutdown.
Too many references; on Linux, when passing too many nested descriptors through a Unix socket.
The connection timed out because the destination did not respond. It is usually caused by a firewall that silently drops the packets, a host that is down or a route that does not get there.
The destination refused the connection: the machine responds, but nothing is listening on that port or a firewall replies with a rejection. Check that the service is running and listening on the right interface, not only on 127.0.0.1.
The destination host is down.
No route to the host: it does not respond to ARP on the local network, or a router or firewall reports that it is unreachable.
An operation is already in progress on the socket, such as a non-blocking connect that has not finished yet.
The operation is in progress: a non-blocking connect has started and will finish later. It is not an error; wait with poll or select.
The file handle is stale: on NFS, the file or directory was deleted or replaced on the server. It is fixed by opening the path again or remounting.
The structure needs cleaning: the file system detected corruption (on ext4 and XFS, under the alias EFSCORRUPTED). Unmount it and run fsck or xfs_repair.
Same value:EFSCORRUPTED
Not a XENIX named type file. It is an unused legacy code.
No XENIX semaphores available. It is an unused legacy code.
Is a XENIX named type file. It is an unused legacy code.
Remote I/O error, for example from an I2C device or a remote disk that did not respond.
The user's or group's disk quota was exceeded.
There is no medium in the device, such as a drive with no disc or an empty card reader.
The medium type is wrong.
The operation was canceled, for example an asynchronous I/O or an io_uring wait.
The required key is not in the kernel keyring. It appears with encrypted file systems, such as fscrypt or eCryptfs, when the key has not been loaded.
The key has expired. PAM and Kerberos also use it when the password or the ticket has expired.
The key has been revoked.
The service rejected the key.
The owner of a robust mutex died without releasing it. The new owner must make the protected state consistent and call pthread_mutex_consistent.
The state protected by a robust mutex cannot be recovered, because the previous owner died and nobody marked it as consistent.
The operation is not possible because the Wi-Fi or Bluetooth radio is blocked by RF-kill. Check rfkill list, the hardware switch or the airplane mode key.
The memory page has a hardware error and the kernel marked it as poisoned.
The file type is not appropriate for the operation. It has long existed on macOS and BSD; on Linux it was added recently.
Too many processes. BSD defines it for the process limit, although in practice fork returns EAGAIN.
The RPC structure is bad (Sun RPC, used by NFS).
The RPC version does not match (Sun RPC, used by NFS).
The RPC program is not available on the server.
The RPC program version does not match.
The procedure does not exist in the RPC program.
Authentication error, for example when mounting an NFS share.
An authenticator is needed for the operation.
The device is powered off.
Device error, for example a printer out of paper.
The executable is not valid.
The executable is for another CPU type, such as an x86_64-only binary on an Apple Silicon Mac without Rosetta 2, or an ARM one on an Intel Mac.
The shared library version does not match.
The Mach-O file is malformed or corrupted.
The extended attribute does not exist; it is the equivalent of Linux's ENODATA. It appears with xattr, for example when removing com.apple.quarantine from a file that does not have it.
No policy is registered with that name in the MAC Framework.
The output queue of the network interface is full.
Insufficient capabilities: returned by calls that a sandbox restricts.
The terminal that controlled the process was closed or the SSH session dropped. Many daemons, such as nginx, sshd or rsyslog, use it as a request to reload their configuration; nohup, tmux and screen prevent it from closing processes on exit.
Keyboard interrupt with Ctrl+C. The program can catch it to shut down cleanly. Exit code 130.
Keyboard quit with Ctrl+\. It terminates the process with a core dump; the JVM, instead, uses it to print the state of its threads.
The processor encountered an illegal instruction: a binary built for a newer CPU (for example, with AVX2 or AVX-512 on a processor that lacks them), corrupted code or a jump into data.
Debug trap: debuggers use it for breakpoints. If it arrives without a debugger, it is usually a failure detected by the program itself, such as Swift's checks on macOS.
The process called abort(): a failed assertion, an uncaught C++ exception or heap corruption detected by the C library (“double free or corruption”). Exit code 134.
Same value:SIGIOT
Bus error: a misaligned memory access on some architectures, or an access to part of an mmap-mapped file that no longer exists because the file was truncated. It also happens when /dev/shm fills up.
Arithmetic exception. Despite the name, the most common cause is an integer division by zero.
Terminates the process immediately: it cannot be caught, blocked or ignored. It is sent by kill -9, by the kernel's OOM killer when memory runs out, and by Docker or Kubernetes when a container exceeds its memory limit (OOMKilled) or does not exit in time after SIGTERM. Exit code 137.
Free signal for each application to use as it sees fit; for example, dd reports its progress and nginx reopens its logs.
Segmentation violation (“Segmentation fault”): an invalid memory access, such as dereferencing a null pointer, going past the end of an array or overflowing the stack with infinite recursion. Exit code 139.
Second free signal for each application to use as it sees fit.
Write to a pipe or socket with no reader. It is normal in cmd | head, where the reader exits first; servers usually ignore it and handle the EPIPE error. Exit code 141.
The timer set with alarm or setitimer expired.
Request for graceful termination. It is the default signal of kill, systemctl stop, docker stop and of Kubernetes when deleting a pod; the process should close its connections and exit. Exit code 143.
Coprocessor stack fault. Not used on current Linux.
A child process exited, stopped or continued. The parent must reap it with wait; if it does not, the child becomes a zombie.
Same value:SIGCLD
Resumes a stopped process, as fg and bg do in the shell.
Stops the process; it cannot be caught or ignored. It is resumed with SIGCONT.
Stop from the terminal with Ctrl+Z. Unlike SIGSTOP, the program can catch it.
A background process tried to read from the terminal.
A background process tried to write to the terminal with stty tostop enabled, or to change its settings.
Urgent (out-of-band) data arrived on a socket. Go uses it internally to interrupt goroutines.
The process exceeded its CPU time limit (ulimit -t).
The process exceeded the maximum file size it is allowed (ulimit -f).
The virtual timer expired, which counts only the CPU time of the process.
The profiling timer, used by profilers, expired.
The terminal window size changed; full-screen programs use it to redraw themselves.
I/O is available on a descriptor configured with O_ASYNC. On Linux, SIGPOLL is the same signal.
Same value:SIGPOLL
Power failure, which UPS software reports to the init system.
Bad system call. Nowadays the usual cause is a seccomp filter that blocks it, as in containers.
Emulation trap (EMT). It exists on macOS and BSD, but not on Linux on x86 or ARM.
Information request with Ctrl+T in the macOS and BSD terminal; many commands respond by showing their progress.
The command finished successfully. It is the only code that means success: any other value indicates an error.
General error; each program decides what it means. The details are usually in what the command wrote to stderr. grep and diff use it with a different meaning: “no matches found” or “the files differ”.
Misuse of a shell builtin or a syntax error in the script. Many programs also use it for invalid options, and grep for actual errors.
The command was used incorrectly: arguments are missing, there are too many or an option is wrong.
The input data has an incorrect format.
An input file does not exist or cannot be read.
The specified user does not exist; it is used mainly by mail programs.
The host name does not exist.
A required service is not available, or something failed that does not fit into another category.
Internal program error.
Operating system error, such as being unable to fork or to create a pipe.
A system file, such as /etc/passwd, is missing or has an error.
An output file cannot be created.
Input/output error while reading or writing a file.
Temporary failure: it is worth retrying later. Mail servers use it to leave the message in the queue.
The remote system responded with something that does not follow the protocol.
Insufficient permissions for the operation.
There is an error in the configuration.
The timeout command terminated it because it exceeded the specified time.
docker run itself failed before running the container, for example because of an incorrect option or a daemon error. GNU timeout also returns it when it is the one that fails.
The file exists, but it cannot be executed: it lacks execute permission, it is a directory or it is a binary for another architecture. In Docker, the container command is not executable.
Command not found: it is not installed, it is not in the PATH or its name is misspelled. In scripts it also appears when the interpreter in the #! line is missing; in Docker, when the container command does not exist in the image.
Codes above 128 indicate that a signal terminated the process, but 128 does not correspond to any. Git uses it for all its fatal errors (“fatal: …”), such as a repository that does not exist or an authentication failure when cloning.
The exit code was out of range: exit -1 arrives as 255, because only 8 bits are kept. ssh also returns it when the connection or authentication fails, to distinguish it from the remote command's code.
The Linux values are those of x86, x86-64 and ARM; Alpha, MIPS, SPARC and PA-RISC number some errno values and signals differently. The English messages are the ones shown by strerror and strsignal in glibc, and by macOS when they differ. Exit codes above 128 are interpreted as 128 plus the signal number, which is the convention of bash, Docker and Kubernetes.
How it works
When a system call fails on Linux, it returns -1 and leaves a number in the errno variable that says why: 2 is ENOENT, the file does not exist; 13 is EACCES, permission denied. strerror turns that number into the text shown on screen, such as “No such file or directory”. Python shows it as [Errno 13], Node.js as code: 'ECONNREFUSED' and Go, Rust or Java with the same text. Numbers 1 to 34 come from the original Unix and are the same on every system; the following ones were numbered by each system in its own way, so ECONNREFUSED is 111 on Linux and 61 on macOS. The name is portable; the number is not.
Signals are notifications that the kernel or another process sends to a process: SIGINT when Ctrl+C is pressed, SIGTERM to ask it to terminate, SIGKILL to terminate it without asking, SIGSEGV when it accesses invalid memory. Each one has a default action, and almost all of them can be caught to do something else. When a signal kills a process, the shell reports an exit code of 128 plus the signal number: 137 is SIGKILL (9), 139 is SIGSEGV (11) and 143 is SIGTERM (15). Docker and Kubernetes use the same convention.
The exit code is the number a program leaves when it finishes: 0 means success and any other value, an error. Only 8 bits are kept, so it ranges from 0 to 255. There are few conventions: 126 and 127 are used by the shell when it cannot execute or cannot find the command, 64 to 78 are defined by BSD's sysexits.h, and the rest is up to each program, like grep, which returns 1 when it finds nothing.
Examples
Last State: Terminated · Reason: OOMKilled · Exit Code: 137137 = 128 + 9 · SIGKILLThe container exceeded its memory limit and the kernel killed it with SIGKILL. Raise the limit in resources.limits.memory or find out why the process uses so much; restarting it does not fix it.Error: connect ECONNREFUSED 127.0.0.1:5432ECONNREFUSED · Linux 111 · macOS 61 · Connection refusedNode.js could not connect to PostgreSQL because nothing is listening on port 5432. If the application runs in a container, 127.0.0.1 is the container itself and not the host machine: use the name of the database service.OSError: [Errno 48] Address already in useEADDRINUSE · Linux 98 · macOS 48The 48 gives away that the program runs on macOS: on Linux the same error is 98. In both cases another process is already using the port; lsof -i :PORT shows which one.Use cases
- Understand an error from an application in Python, Node.js, Go or C that only shows the errno number or name.
- Find out from its exit code why a Docker container stopped or a Kubernetes pod keeps restarting.
- Map a macOS errno number to the right name, which from 35 onwards does not match the Linux one.
- Interpret the exit code of a failed script, cron job or CI job.
- Choose which signal to send with kill and know what the process does if it does not catch it.
- Write portable error handling that compares by name instead of by number.
Frequently asked questions
What does exit code 137 mean?
That the process was terminated by signal 9, SIGKILL (128 + 9). The most common cause is memory: the container exceeded its limit, which Kubernetes reports as OOMKilled, or the kernel's OOM killer chose that process, which shows up in dmesg as “Out of memory: Killed process”. It also happens with docker kill, or when the process does not exit within the grace period after SIGTERM: 10 seconds in docker stop and 30 in Kubernetes.
What is the difference between SIGTERM and SIGKILL?
SIGTERM asks the process to terminate, and the process can catch it to close connections, save data and exit. With SIGKILL, the kernel terminates it on the spot, and the process can do nothing about it. The right thing is to send SIGTERM, wait a few seconds and resort to SIGKILL only if it is still alive, which is what systemd, docker stop and Kubernetes do.
Why does the same errno have a different number on macOS?
Because POSIX defines the names but not the numbers. From 1 to 34, every system inherited those of the original Unix; after that, BSD, which macOS comes from, and System V, which Linux followed, numbered them separately. That is why you should always compare by name, with errno.ECONNREFUSED in Python, err.code in Node.js or the constant in C, and not by number.
What is the difference between EACCES and EPERM?
EACCES (“Permission denied”) means that the permissions of the file or of some directory in the path do not allow it, or that an ACL or SELinux prevents it: it is solved with chmod, chown or the corresponding policy. EPERM (“Operation not permitted”) means that the operation itself requires privileges, regardless of permissions, such as changing the owner of a file or killing another user's process: it takes root, a capability or removing an attribute such as the immutable one.
How do I see the exit code of a command or a container?
In bash and zsh, echo $? shows the one from the last command; in PowerShell, $LASTEXITCODE. In Docker, docker ps -a shows it in the STATUS column, as “Exited (137)”. In Kubernetes, kubectl describe pod shows it under “Last State: Terminated”, along with the reason, such as OOMKilled or Error.