Numeric Unix Error Messages
© December 2001 Tony Lawrence
December 2001
It's an unfortunate fact that many programmers are lazy about
error messages. Very often, all you get is a cryptic "Error 5", and
you may be lucky to get that: sometimes all you get is an error
return that you have to examine yourself with "echo $?". You can't
even depend on that being the actual Unix error, but even if it is,
what does it mean?
Well, every Unix/Linux system includes various ".h" files that
describe the numeric errors returned by kernel system calls.
Unfortunately, those files are only a little bit more illuminating
than the numeric errors themselves. For example, here's a couple of
lines from a Linux system:
#define EPERM 1 /* Operation not permitted */
...
#define EACCES 13 /* Permission denied */
What's the difference? When would you get one versus the other?
This article attempts to more fully explain what these errors mean
and to give examples of what might cause them.
I'm only going to look at the first 32 of these; there are many
more, but these are the more common. Understand that the numeric
codes can vary from Unix to Unix- you really need to look in the
/usr/include files to find the symbolic names, and even those are
used in slightly different ways- certain system calls on a BSD
system, for example, will return a different error result than they
will on a SysV Unix. However, most of that kind of thing is
esoteric detail of concern only to programmers working on multiple
platforms.
Even where the error numbers and the symbolic constants are the
same, the comments may vary. For example, while SCO Unix and Linux
systems would look almost exactly alike for the first 30 or 40
errors, some of the comments are markedly different, and higher
numbered errors are defined completely differently. So, the thing
to keep in mind is that just because you've seen a particular error
on a particular platform doesn't mean it is the same somewhere
else. There's also nothing that prevents a programmer from
misusing these constants in their own error returns, either through
ignorance or simple misunderstanding of the historical use of
these.
And it also means that the descriptions of what might cause a
specific error are heavily dependent on that word "might". Please
keep that in mind as you read this.
On a Linux system with source installed, you can cd to
/usr/src/linux*/kernel and do a grep -l for the symbolic constant
you are interested in. For example, here's the places where EPERM
is referenced on a 7.2 Red Hat system:
acct.c
capability.c
fork.c
kmod.c
module.c
printk.c
ptrace.c
sched.c
signal.c
sys.c
sysctl.c
time.c
uid16.c
On Apple OS X, it's even easier. Open Terminal and use "macerror":
$ macerror -5002
Mac OS error -5002 (afpBadUAM): Unknown user authentication method specified
For other Unix systems, pawing through documentation is the only
way. For this article, I used:
Unix Internals by
Steve Pate
Unix Network Programming
by W. Richard Stevens
The Magic Garden by
Berny Goodhart and James Cox
Advanced Programming in
the Unix Environment by W. Richard Stevens
Again, keep in mind that this is all examples, and may not apply
to your specific platform. The system calls shown as examples may
not be the only functions that will return these errors; you really
need access to the source to know that.
- #define EPERM 1 /* Operation not permitted */ (Linux)
- #define EPERM 1 /* Not owner */ (SCO Unix)
This error is returned by kernel routines when the calling
process lacks the necessary authority. For example, if you, as an
ordinary user, call the "setuid()" function trying to change to
someone else's ID, it will fail and EPERM will be returned. The
"getpgrp()" uses this return if you try to get the process ID of a
process not part of your login session.
- #define ENOENT 2 /* No such file or directory */
This one's easy: You are trying to open a file that doesn't
exist and you haven't specified to create it. However, it can also
be returned for trying to open a non-existent IPC channel, or if
one of the directories in a pathname does not exist.
- #define ESRCH 3 /* No such process */
The kill() function returns this if you pass it a non-existent
PID. Trying to delete a non-existent route from the routing table
also uses this.
- #define EINTR 4 /* Interrupted system call */
When a program reads from a "slow" device (a terminal, for
example), that read can sit returning nothing for a long time, and
it may be that the process is sent a signal during that wait. The
programmer needs to know whether the read returned because it got
its data, because there is no more data, or if a signal interrupted
it. That's the purpose of this error, though it is also used for
the pause() function and some IPC functions.
- #define EIO 5 /* I/O error */
The catchall for all manner of unexpected hardware errors. It
could be from a physical error, but additionally, an orphaned
process (a process whose parent has died) that attempts to read
from standard input will get this. BSD systems return this if you
try to open a pty device that is already in use. An attempt to read
from a stream that is closed will return EIO, as will a disk read
or write that is outside of the physical bounds of the device. An
open of /dev/tty when the process has no controlling tty will spit
back EIO also.
- #define ENXIO 6 /* No such device or address */
This can be the result of opening a FIFO write-only, with
O_NDELAY set, but no process is reading the FIFO. It may also be
returned if I/O is attempted on a sub-device of a driver that does
not exist (for example, a tape device that has not been defined in
the kernel), or if I/O is attempted beyond the limits of the
device.
- #define E2BIG 7 /* Arg list too long */
This can be returned by exec() when too much is passed. You
could see that, for example, if you tried to run "ls" on a
directory with too many files. But it also can come from attempting
to pass too much data to an IPC message queue, and from trying to
do too many operations in a semop() (semaphore) call .
- #define ENOEXEC 8 /* Exec format error */
Ask the kernel to run a binary it doesn't recognize as valid and
this is what you get. Assumiong you aren't rrying to execute
arbitrary data and haven't copied a binary from some other OS, you
probably have a corrupt file.
- #define EBADF 9 /* Bad file number */
When a program opens a file, open() returns a numeric file
descriptor. Further calls to read() or write() use that descriptor-
if it is not valid (never opened it, or closed it prior to the read
or write), this is returned.
- #define ECHILD 10 /* No child processes */
When a program spawns off a child process, it may wait() for the
exit status of the child. If it tries to wait() for a child that
doesn't exist, or re-issues a wait() for the same child, it gets
this. This is also used when the parent has set its signals so that
children can exit without being waited for; in that case it just
indicates that all children have exited.
- #define EAGAIN 11 /* Try again */ (Linux)
- #define EAGAIN 11 /* No more processes */ (SCO Unix)
Good advice in general, but EAGAIN is generally used with
non-blocking I/O in the case where part or all of the data you
wanted to read or write can't be completed just now because of your
non-blocking request. This is true for files as well as IPC
communications. Depending on your platform, this or EACESS may be
returned by fcntl() when it cannot grant a lock you have requested.
On BSD platforms, bind() can return this when trying to bind a
reserved port number if all are in use.
See Fork failing, but WHY?? for a discussion about trying to solve such a problem.
- #define ENOMEM 12 /* Out of memory */ (Linux)
- #define ENOMEM 12 /* Not enough space */ (SCO Unix)
If you try to exec() another process or just ask for more memory
in this process, the kernel will give back this if it can't give
you what you need.
- #define EACCES 13 /* Permission denied */
Simply, file permissions don't let you do the open() you
requested. But also see EAGAIN above. This can also be returned by
getspnam() when you aren't root.
- #define EFAULT 14 /* Bad address */
A bad memory address, specifically one that doesn't belong to
the current process. Typically a programming error causes this.
- #define ENOTBLK 15 /* Block device required */
Try to set disk quotas on something that isn't a block device
and this is the error you'll get. Mounting/unmounting and other
filesystem related functions will also use this return.
- #define EBUSY 16 /* Device or resource busy */ (Linux)
- #define EBUSY 16 /* Device busy */ (SCO Unix)
Trying to unmount a file system that is in use will generate
this. Although less likeky in practice, trying to remove a
directory that has a filesystem mounted on it will also complain in
this manner. And, while a filesystem is being mounted or unmounted,
a process that attempts to access it will find it locked and will
get this error.
- #define EEXIST 17 /* File exists */
You get this when you explicitly try to open a file with O_CREAT
and O_EXCL set, or try to create a new IPC structure with IPC_CREAT
and IPC_EXCL but the file or IPC already exists. The link()
function also fails with EEXIST if the "new" file is not.
- #define EXDEV 18 /* Cross-device link */
You can't link across filesystems (that's what symbolic links
are for). Trying to rename a directory to some other filesystem is
the same problem.
- #define ENODEV 19 /* No such device */
Any ioctl requests will generate this when applied to a device
that doesn't support ioctl's- like /dev/null. Inappropriate
requests ( reading from a write only device) may return this or
EINVAL- there's seems to be plenty of confusion as to which to
use.
- #define ENOTDIR 20 /* Not a directory */
Any system call that expects a directory and doesn't get one
will complain with this.
- #define EISDIR 21 /* Is a directory */
Attempting write() on a directory will get you this.
- #define EINVAL 22 /* Invalid argument */
EINVAL gets used a lot. TCP has the concept of "out of band
data" (urgent data). If a reading process checks for this, and
there isn't any, it get EINVAL. The plock() function ( which locks
areas of a process into memory) returns this if you attempt to use
it twice on the same memory segment. If you try to specify SIGKILL
or SIGSTOP to sigaction(), you'll get this return. The readv() and
writev() calls complain this way if you give them too large an
array of buffers. As mentioned above, drivers may return this for
inappropriate ioctl() calls. The mmap() call will return this if
you've specified a specific address but that address can't be used.
A seek() to before the beginning of a file returns this. Streams
use this if you attempt to link a stream onto itself. It's used for
many IPC errors also.
- #define ENFILE 23 /* File table overflow */
When the system itself can open no more files, this is the error
returned.
- #define EMFILE 24 /* Too many open files */
When a process tries to execeed the maximum number of open file
descriptors allowed, open() returns this. The "file" could also be
a network socket.
- #define ENOTTY 25 /* Not a typewriter */
While a lot of people programming Unix and Linux may never have
seen a real typewriter, would anyone ever confuse a computer with a
typewriter? Seriously, this is the generic and time-honored Unix
complaint when you try to do something that needs a character
device. Ioctl's return this when applied to ordinary files, for
example. So will attempts to get or set attributes ( tcgettattr()
tcsetattr() ) on something not a terminal device. So will
tcdrain(), tcflush(), tcflow() and tcsendbreak().
- #define ETXTBSY 26 /* Text file busy */
A "text" file is a program- an executing binary. It's illegal to
write to a binary while it is executing- simply because allowing
that complicates swapping and paging. Interestingly, some Unixes
don't have this at all: Unixware, for example returns different
errors.
- #define EFBIG 27 /* File too large */
You've tried to extend a file byond the maximum supported size.
That could be the maximum size supported by the file system or it
could be a per-process limit imposed on you specifically.
- #define ENOSPC 28 /* No space left on device */
Ooops. Time for a larger disk. IPC creates can also return
this.
- #define ESPIPE 29 /* Illegal seek */
You aren't allowed to seek on a pipe. Socket calls can also
return this.
- #define EROFS 30 /* Read-only file system */
Not much to be said about that.
- #define EMLINK 31 /* Too many links */
Too many links on a file system would be my guess, but I can't
find a thing on this in source or books. Perhaps you'd get this if
you had a recursive directory looping back on itself.
- #define EPIPE 32 /* Broken pipe */
Fairly obvious- the reading or writing side of a pipe drops out
of the game.
Here's some odd ones:
#define ENOPKG 65
#define EISNAM 139
At Rare Error 65 (ENOPKG) occurrence on open() call, Bela Lubkin noted:
There are very few things in the kernel that return ENOPKG. Candidates include the System V shared memory driver ("shm"), the Xenix shared data driver ("xsd"), and the Advanced Power Management drivers ("uapm" and "pwr"). Each of these drivers has "stubs.c" code -- code that gets linked into the kernel when the driver is _not_ present -- that returns ENOPKG for certain operations.
It isn't clear to me whether any of these could return ENOPKG for an
open() call. More typically it would be on calling shmsys(), any of the
xsd*() functions, and on attempting certain ioctls with the APM stuff.
But... there exists an obscure file type which is an on-disk
representation of a Xenix Shared Data memory segment. If you had one of
those and tried to open it, it _might_ return ENOPKG if "xsd" wasn't
linked into your kernel.
Or might not. I just tried it and:
$ mknod test-m m
$ cat test-m
cat: cannot open test-m: Is a name file (error 139)
EISNAM is not ENOPKG.
Got something to add? Send me email.
4 comments
Thu Nov 17 03:34:09 2005: 1358 George
Thanks a lot. The article was very informative and was a great help.
Thu Nov 17 04:39:24 2005: 1359 BigDumbDinosaur
Don't forget about the perror library call. It will print an error message to STDERR that will be determined by the error code returned from the most recent system or library call. You can use it something like this: You can also use this mechanism to log errors by closing STDERR and reopening the channel to a file.
Tue Apr 15 18:12:20 2008: 4042 anonymous
Superb!! Exactly what I wanted!
Tue Apr 6 16:28:27 2010: 8376 TonyLawrence
I came across this recently: Universal Error Numbering System:
(link)
Probably won't go anywhere, but there it is.
------------------------
Printer Friendly Version
Numeric Unix Error Messages Copyright © December 2001 Tony Lawrence
Related Articles
Have you tried Searching this site?
This is a Unix/Linux resource website. It contains technical articles about Unix, Linux and general computing related subjects, opinion, news, help files, how-to's, tutorials and more.
Contact us
Printer Friendly Version