Skip to content

/codes/c/errno-codes

C errno codes: ENOENT, EACCES, EINVAL, ERANGE and what each value means

verified onenvironmentlocal · linux 6.18.44-fc-v233 x64 · GNU bash 5.2.21updated
tool
C
versions
C99, C11, C17, POSIX.1-2001
os
linux, macos, windows

errno is the integer a C library or system call sets to say why it failed, for example ENOENT (2, no such file or directory) after fopen on a missing path. Read it only after a function has signalled failure, and print it with strerror(errno) or perror(). The names below are portable across POSIX systems; the numbers shown are the Linux values.

Common errno codes (Linux)

NameValueMeaningTypical cause
EPERM1Operation not permittedChanging owner or using a privileged call without the right
ENOENT2No such file or directoryPath or one of its components does not exist, or a dangling symlink
EINTR4Interrupted system callA signal arrived while a call was blocked; retry the call
EIO5Input/output errorHardware or filesystem failure while reading or writing
EBADF9Bad file descriptorDescriptor is closed or was never opened
EAGAIN11Resource temporarily unavailableNon-blocking call has no data yet; may equal EWOULDBLOCK
ENOMEM12Cannot allocate memorymalloc or mmap could not get memory
EACCES13Permission deniedFile or directory permissions forbid the access
EEXIST17File existsCreating a file or directory that is already there
ENOTDIR20Not a directoryA path component is a file where a directory is needed
EISDIR21Is a directoryOpening a directory for writing
EINVAL22Invalid argumentA parameter has a value the call does not accept
EMFILE24Too many open filesThe process hit its RLIMIT_NOFILE limit
ENOSPC28No space left on deviceDisk or quota full
EPIPE32Broken pipeWriting to a pipe or socket whose reader has gone
EDOM33Numerical argument out of domainMath function given an argument outside its domain
ERANGE34Numerical result out of rangeResult too large, as with strtol on overflow
ECONNREFUSED111Connection refusedNothing is listening on the target port

Only EDOM, EILSEQ and ERANGE come from ISO C itself. The rest are defined by POSIX, so they exist on Linux and macOS but are not guaranteed by a bare C compiler on every platform.

This program prints the number and the message for several names, so you can check the table against your C library.

bash
mkdir -p /tmp/work && cd /tmp/work
cat > errno_table.c <<'EOF'
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define SHOW(e) printf("%-7s %3d %s\n", #e, e, strerror(e))
int main(void) {
    SHOW(EPERM); SHOW(ENOENT); SHOW(EACCES); SHOW(EEXIST);
    SHOW(EINVAL); SHOW(ENOMEM); SHOW(ERANGE);
    return 0;
}
EOF
gcc -Wall -o errno_table errno_table.c && ./errno_table

Output

EPERM     1 Operation not permitted
ENOENT    2 No such file or directory
EACCES   13 Permission denied
EEXIST   17 File exists
EINVAL   22 Invalid argument
ENOMEM   12 Cannot allocate memory
ERANGE   34 Numerical result out of range

Read errno correctly

  1. Check the return value first. fopen returns NULL, open returns -1; only then is errno meaningful.
  2. Save it at once. Calls such as printf or fclose can change errno. Write int saved = errno; right after the failing call.
  3. Clear it before calls that signal errors only through errno. strtol returns 0 or LONG_MAX on failure and sets ERANGE; set errno = 0 before the call and test it afterwards, as shown in convert a string to int in C.
  4. Do not print it when nothing failed. It can hold a stale value from an earlier call.

strerror, perror and thread safety

perror("open") prints open: followed by the message to standard error. strerror(errno) returns the same text as a string, but the buffer may be shared, so use strerror_r in threaded programs. errno itself is thread-local, so each thread sees its own value.

Choosing a response

  • EINTR and EAGAIN are usually retried, not reported.
  • ENOENT, EACCES and EEXIST are user-facing: show the path and strerror text.
  • ENOMEM, EIO and ENOSPC usually mean the operation cannot continue; clean up and exit with a non-zero status.
  • EINVAL normally points to a bug in the arguments you passed.

FAQ

Why does errno hold a value after a function succeeded?

Because no function sets errno back to zero. The Linux errno manual says a successful call is even allowed to change it, so the value is meaningful only right after a call that reported failure through its return value. Check the return value first, then read errno.

Are the numeric errno values the same on every system?

No. Only the names are portable. The numbers in the table are the Linux values, and macOS, Windows and other Unix systems use different numbers for some names. Always compare against the macro, such as ENOENT, and print text with strerror() or perror() rather than hard-coding numbers.

Is errno safe to use in a multithreaded program?

Yes. The Linux manual states that errno is thread-local, so setting it in one thread does not change its value in any other thread. Read it in the same thread that made the failing call, and copy it to a local variable before calling anything else that could overwrite it.

Sources