|
|
|
# Errors
|
|
|
|
|
|
|
|
<!--type=misc-->
|
|
|
|
|
|
|
|
Errors generated by Node.js fall into two categories: JavaScript errors and system
|
|
|
|
errors. All errors inherit from or are instances of JavaScript's [`Error`][]
|
|
|
|
class and are guaranteed to provide *at least* the attributes available on that
|
|
|
|
class.
|
|
|
|
|
|
|
|
When an operation is not permitted due to language-syntax or
|
|
|
|
language-runtime-level reasons, a **JavaScript error** is generated and thrown
|
|
|
|
as an **exception**. If an operation is not allowed due to system-level
|
|
|
|
restrictions, a **system error** is generated. Client code is then given the
|
|
|
|
opportunity to **intercept** this error based on how the API **propagates** it.
|
|
|
|
|
|
|
|
The style of API called determines how generated errors are handed back, or
|
|
|
|
**propagated**, to client code, which in turn informs how the client may **intercept**
|
|
|
|
the error. Exceptions can be intercepted using the [`try / catch` construct][];
|
|
|
|
other propagation strategies are covered [below][].
|
|
|
|
|
|
|
|
## Error Propagation and Interception
|
|
|
|
|
|
|
|
<!--type=misc-->
|
|
|
|
|
|
|
|
All Node.js APIs will treat invalid arguments as exceptional -- that is, if passed
|
|
|
|
invalid arguments, they will *immediately* generate and throw the error as an
|
|
|
|
exception, even if they are an otherwise asynchronous API.
|
|
|
|
|
|
|
|
Synchronous APIs (like [`fs.readFileSync`][]) will throw the error. The act of
|
|
|
|
*throwing* a value (in this case, the error) turns the value into an **exception**.
|
|
|
|
Exceptions may be caught using the [`try { } catch(err) { }`][] construct.
|
|
|
|
|
|
|
|
Asynchronous APIs have **two** mechanisms for error propagation; one mechanism
|
|
|
|
for APIs that represent a single operation, and one for APIs that represent
|
|
|
|
multiple operations over time.
|
|
|
|
|
|
|
|
### Error events
|
|
|
|
|
|
|
|
<!--type=misc-->
|
|
|
|
|
|
|
|
The other mechanism for providing errors is the `'error'` event. This is
|
|
|
|
typically used by [stream-based][] and [event emitter-based][] APIs, which
|
|
|
|
themselves represent a series of asynchronous operations over time (versus a
|
|
|
|
single operation that may pass or fail). If no `'error'` event handler is
|
|
|
|
attached to the source of the error, the error will be thrown. At this point,
|
|
|
|
it will crash the process as an unhandled exception unless [domains][] are
|
|
|
|
employed appropriately or [`process.on('uncaughtException')`][] has a handler.
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
var net = require('net');
|
|
|
|
|
|
|
|
var connection = net.connect('localhost');
|
|
|
|
|
|
|
|
// adding an 'error' event handler to a stream:
|
|
|
|
connection.on('error', function(err) {
|
|
|
|
// if the connection is reset by the server, or if it can't
|
|
|
|
// connect at all, or on any sort of error encountered by
|
|
|
|
// the connection, the error will be sent here.
|
|
|
|
console.error(err);
|
|
|
|
});
|
|
|
|
|
|
|
|
connection.pipe(process.stdout);
|
|
|
|
```
|
|
|
|
|
|
|
|
The "throw when no error handlers are attached behavior" is not limited to APIs
|
|
|
|
provided by Node.js -- even user created event emitters and streams will throw
|
|
|
|
errors when no error handlers are attached. An example:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
var EventEmitter = require('events');
|
|
|
|
|
|
|
|
var ee = new EventEmitter();
|
|
|
|
|
|
|
|
setImmediate(function() {
|
|
|
|
// this will crash the process because no 'error' event
|
|
|
|
// handler has been added.
|
|
|
|
ee.emit('error', new Error('This will crash'));
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
As with node style callbacks, errors generated this way *cannot* be intercepted
|
|
|
|
by `try { } catch(err) { }` -- they happen *after* the calling code has already
|
|
|
|
exited.
|
|
|
|
|
|
|
|
### Node style callbacks
|
|
|
|
|
|
|
|
<!--type=misc-->
|
|
|
|
|
|
|
|
Single operation APIs take "node style callbacks" -- a
|
|
|
|
function provided to the API as an argument. The node style callback takes
|
|
|
|
at least **one** argument -- `error` -- that will either be `null` (if no error
|
|
|
|
was encountered) or an `Error` instance. For instance:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
var fs = require('fs');
|
|
|
|
|
|
|
|
fs.readFile('/some/file/that/does-not-exist', function nodeStyleCallback(err, data) {
|
|
|
|
console.log(err) // Error: ENOENT
|
|
|
|
console.log(data) // undefined / null
|
|
|
|
});
|
|
|
|
|
|
|
|
fs.readFile('/some/file/that/does-exist', function(err, data) {
|
|
|
|
console.log(err) // null
|
|
|
|
console.log(data) // <Buffer: ba dd ca fe>
|
|
|
|
})
|
|
|
|
```
|
|
|
|
|
|
|
|
Note that `try { } catch(err) { }` **cannot** intercept errors generated by
|
|
|
|
asynchronous APIs. A common mistake for beginners is to try to use `throw`
|
|
|
|
inside their node style callback:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
// THIS WILL NOT WORK:
|
|
|
|
var fs = require('fs');
|
|
|
|
|
|
|
|
try {
|
|
|
|
fs.readFile('/some/file/that/does-not-exist', function(err, data) {
|
|
|
|
// mistaken assumption: throwing here...
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} catch(err) {
|
|
|
|
// ... will be caught here -- this is incorrect!
|
|
|
|
console.log(err); // Error: ENOENT
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
This will not work! By the time the node style callback has been called, the
|
|
|
|
surrounding code (including the `try { } catch(err) { }` will have already
|
|
|
|
exited. Throwing an error inside a node style callback **will crash the process** in most cases.
|
|
|
|
If [domains][] are enabled, they may intercept the thrown error; similarly, if a
|
|
|
|
handler has been added to `process.on('uncaughtException')`, it will intercept
|
|
|
|
the error.
|
|
|
|
|
|
|
|
## JavaScript Errors
|
|
|
|
|
|
|
|
<!--type=misc-->
|
|
|
|
|
|
|
|
JavaScript errors typically denote that an API is being used incorrectly, or that
|
|
|
|
there is a problem with the program as written.
|
|
|
|
|
|
|
|
### Class: Error
|
|
|
|
|
|
|
|
<!--type=class-->
|
|
|
|
|
|
|
|
A general error object. Unlike other error objects, `Error` instances do not
|
|
|
|
denote any specific circumstance of why the error occurred. Errors capture a
|
|
|
|
"stack trace" detailing the point in the program at which they were
|
|
|
|
instantiated, and may provide a description of the error.
|
|
|
|
|
|
|
|
**Note**: Node.js will generate this class of error to encapsulate system
|
|
|
|
errors as well as plain JavaScript errors.
|
|
|
|
|
|
|
|
#### new Error(message)
|
|
|
|
|
|
|
|
Instantiates a new `Error` object and sets its `.message` property to the provided
|
|
|
|
message. Its `.stack` will represent the point in the program at which `new Error`
|
|
|
|
was called. Stack traces are subject to [V8's stack trace API][].
|
|
|
|
Stack traces only extend to the beginning of synchronous code execution, *or* a number of frames given by
|
|
|
|
`Error.stackTraceLimit`, whichever is smaller.
|
|
|
|
|
|
|
|
#### Error.captureStackTrace(targetObject[, constructorOpt])
|
|
|
|
|
|
|
|
Creates a `.stack` property on `targetObject`, which when accessed returns
|
|
|
|
a string representing the location in the program at which `Error.captureStackTrace`
|
|
|
|
was called.
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
var myObject = {};
|
|
|
|
|
|
|
|
Error.captureStackTrace(myObject);
|
|
|
|
|
|
|
|
myObject.stack // similar to `new Error().stack`
|
|
|
|
```
|
|
|
|
|
|
|
|
The first line of the trace, instead of being prefixed with `ErrorType:
|
|
|
|
message`, will be the result of `targetObject.toString()`.
|
|
|
|
|
|
|
|
`constructorOpt` optionally accepts a function. If given, all frames above
|
|
|
|
`constructorOpt`, including `constructorOpt`, will be omitted from the generated
|
|
|
|
stack trace.
|
|
|
|
|
|
|
|
This is useful for hiding implementation details of error generation from the
|
|
|
|
end user. A common way of using this parameter is to pass the current Error
|
|
|
|
constructor to it:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
|
|
function MyError() {
|
|
|
|
Error.captureStackTrace(this, MyError);
|
|
|
|
}
|
|
|
|
|
|
|
|
// without passing MyError to captureStackTrace, the MyError
|
|
|
|
// frame would should up in the .stack property. by passing
|
|
|
|
// the constructor, we omit that frame and all frames above it.
|
|
|
|
new MyError().stack
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
#### Error.stackTraceLimit
|
|
|
|
|
|
|
|
Property that determines the number of stack frames collected by a stack trace
|
|
|
|
(whether generated by `new Error().stack` or `Error.captureStackTrace(obj)`).
|
|
|
|
|
|
|
|
The initial value is `10`. It may be set to any valid JavaScript number, which
|
|
|
|
will affect any stack trace captured *after* the value has been changed. If set
|
|
|
|
to a non-number value, stack traces will not capture any frames and will report
|
|
|
|
`undefined` on access.
|
|
|
|
|
|
|
|
#### error.message
|
|
|
|
|
|
|
|
A string of the value passed to `Error()` upon instantiation. The message will
|
|
|
|
also appear in the first line of the stack trace of the error. Changing this
|
|
|
|
property *may not* change the first line of the stack trace.
|
|
|
|
|
|
|
|
#### error.stack
|
|
|
|
|
|
|
|
A property that, when **accessed**, returns a string representing the point in the program
|
|
|
|
at which this error was instantiated. An example stacktrace follows:
|
|
|
|
|
|
|
|
Error: Things keep happening!
|
|
|
|
at /home/gbusey/file.js:525:2
|
|
|
|
at Frobnicator.refrobulate (/home/gbusey/business-logic.js:424:21)
|
|
|
|
at Actor.<anonymous> (/home/gbusey/actors.js:400:8)
|
|
|
|
at increaseSynergy (/home/gbusey/actors.js:701:6)
|
|
|
|
|
|
|
|
The first line is formatted as `<error class name>: <error message>`, and it is followed
|
|
|
|
by a series of stack frames (each line beginning with "at "). Each frame describes
|
|
|
|
a call site in the program that lead to the error being generated. V8 attempts to
|
|
|
|
display a name for each function (by variable name, function name, or object
|
|
|
|
method name), but occasionally it will not be able to find a suitable name. If
|
|
|
|
V8 cannot determine a name for the function, only location information will be
|
|
|
|
displayed for that frame. Otherwise, the determined function name will be displayed
|
|
|
|
with location information appended in parentheses.
|
|
|
|
|
|
|
|
Frames are **only** generated for JavaScript functions. If, for example, execution
|
|
|
|
synchronously passes through a C++ addon function called `cheetahify`, which itself
|
|
|
|
calls a JavaScript function, the frame representing the `cheetahify` call will **not**
|
|
|
|
be present in stacktraces:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
var cheetahify = require('./native-binding.node');
|
|
|
|
|
|
|
|
function makeFaster() {
|
|
|
|
// cheetahify *synchronously* calls speedy.
|
|
|
|
cheetahify(function speedy() {
|
|
|
|
throw new Error('oh no!');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
makeFaster(); // will throw:
|
|
|
|
// /home/gbusey/file.js:6
|
|
|
|
// throw new Error('oh no!');
|
|
|
|
// ^
|
|
|
|
// Error: oh no!
|
|
|
|
// at speedy (/home/gbusey/file.js:6:11)
|
|
|
|
// at makeFaster (/home/gbusey/file.js:5:3)
|
|
|
|
// at Object.<anonymous> (/home/gbusey/file.js:10:1)
|
|
|
|
// at Module._compile (module.js:456:26)
|
|
|
|
// at Object.Module._extensions..js (module.js:474:10)
|
|
|
|
// at Module.load (module.js:356:32)
|
|
|
|
// at Function.Module._load (module.js:312:12)
|
|
|
|
// at Function.Module.runMain (module.js:497:10)
|
|
|
|
// at startup (node.js:119:16)
|
|
|
|
// at node.js:906:3
|
|
|
|
```
|
|
|
|
|
|
|
|
The location information will be one of:
|
|
|
|
|
|
|
|
* `native`, if the frame represents a call internal to V8 (as in `[].forEach`).
|
|
|
|
* `plain-filename.js:line:column`, if the frame represents a call internal to Node.js.
|
|
|
|
* `/absolute/path/to/file.js:line:column`, if the frame represents a call in a user program, or its dependencies.
|
|
|
|
|
|
|
|
It is important to note that the string representing the stacktrace is only
|
|
|
|
generated on **access**: it is lazily generated.
|
|
|
|
|
|
|
|
The number of frames captured by the stack trace is bounded by the smaller of
|
|
|
|
`Error.stackTraceLimit` or the number of available frames on the current event
|
|
|
|
loop tick.
|
|
|
|
|
|
|
|
System-level errors are generated as augmented `Error` instances, which are detailed
|
|
|
|
[below](#errors_system_errors).
|
|
|
|
|
|
|
|
### Class: RangeError
|
|
|
|
|
|
|
|
A subclass of `Error` that indicates that a provided argument was not within the
|
|
|
|
set or range of acceptable values for a function; whether that be a numeric
|
|
|
|
range, or outside the set of options for a given function parameter. An example:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
require('net').connect(-1); // throws RangeError, port should be > 0 && < 65536
|
|
|
|
```
|
|
|
|
|
|
|
|
Node.js will generate and throw `RangeError` instances *immediately* -- they are a form
|
|
|
|
of argument validation.
|
|
|
|
|
|
|
|
### Class: ReferenceError
|
|
|
|
|
|
|
|
A subclass of `Error` that indicates that an attempt is being made to access a variable
|
|
|
|
that is not defined. Most commonly it indicates a typo, or an otherwise broken program.
|
|
|
|
While client code may generate and propagate these errors, in practice only V8 will do
|
|
|
|
so.
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
doesNotExist; // throws ReferenceError, doesNotExist is not a variable in this program.
|
|
|
|
```
|
|
|
|
|
|
|
|
`ReferenceError` instances will have an `.arguments` member that is an array containing
|
|
|
|
one element -- a string representing the variable that was not defined.
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
try {
|
|
|
|
doesNotExist;
|
|
|
|
} catch(err) {
|
|
|
|
err.arguments[0] === 'doesNotExist';
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Unless the userland program is dynamically generating and running code,
|
|
|
|
ReferenceErrors should always be considered a bug in the program, or its
|
|
|
|
dependencies.
|
|
|
|
|
|
|
|
### Class: SyntaxError
|
|
|
|
|
|
|
|
A subclass of `Error` that indicates that a program is not valid JavaScript.
|
|
|
|
These errors may only be generated and propagated as a result of code
|
|
|
|
evaluation. Code evaluation may happen as a result of `eval`, `Function`,
|
|
|
|
`require`, or [vm][]. These errors are almost always indicative of a broken
|
|
|
|
program.
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
try {
|
|
|
|
require("vm").runInThisContext("binary ! isNotOk");
|
|
|
|
} catch(err) {
|
|
|
|
// err will be a SyntaxError
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
SyntaxErrors are unrecoverable from the context that created them – they may only be caught
|
|
|
|
by other contexts.
|
|
|
|
|
|
|
|
### Class: TypeError
|
|
|
|
|
|
|
|
A subclass of `Error` that indicates that a provided argument is not an allowable
|
|
|
|
type. For example, passing a function to a parameter which expects a string would
|
|
|
|
be considered a TypeError.
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
require('url').parse(function() { }); // throws TypeError, since it expected a string
|
|
|
|
```
|
|
|
|
|
|
|
|
Node.js will generate and throw `TypeError` instances *immediately* -- they are a form
|
|
|
|
of argument validation.
|
|
|
|
|
|
|
|
### Exceptions vs. Errors
|
|
|
|
|
|
|
|
<!--type=misc-->
|
|
|
|
|
|
|
|
A JavaScript exception is a value that is thrown as a result of an invalid operation or
|
|
|
|
as the target of a `throw` statement. While it is not required that these values are instances of
|
|
|
|
`Error` or classes which inherit from `Error`, all exceptions thrown by Node.js or the JavaScript
|
|
|
|
runtime *will* be instances of Error.
|
|
|
|
|
|
|
|
Some exceptions are *unrecoverable* at the JavaScript layer. These exceptions will always bring
|
|
|
|
down the process. These are usually failed `assert()` checks or `abort()` calls in the C++ layer.
|
|
|
|
|
|
|
|
## System Errors
|
|
|
|
|
|
|
|
System errors are generated in response to a program's runtime environment.
|
|
|
|
Ideally, they represent operational errors that the program needs to be able to
|
|
|
|
react to. They are generated at the syscall level: an exhaustive list of error
|
|
|
|
codes and their meanings is available by running `man 2 intro` or `man 3 errno`
|
|
|
|
on most Unices; or [online][].
|
|
|
|
|
|
|
|
In Node.js, system errors are represented as augmented `Error` objects -- not full
|
|
|
|
subclasses, but instead an error instance with added members.
|
|
|
|
|
|
|
|
### Class: System Error
|
|
|
|
|
|
|
|
#### error.code
|
|
|
|
#### error.errno
|
|
|
|
|
|
|
|
A string representing the error code, which is always `E` followed by capital
|
|
|
|
letters, and may be referenced in `man 2 intro`.
|
|
|
|
|
|
|
|
#### error.syscall
|
|
|
|
|
|
|
|
A string representing the [syscall][] that failed.
|
|
|
|
|
|
|
|
### Common System Errors
|
|
|
|
|
|
|
|
This list is **not exhaustive**, but enumerates many of the common system errors when
|
|
|
|
writing a Node.js program. An exhaustive list may be found [here][online].
|
|
|
|
|
|
|
|
#### EACCES: Permission denied
|
|
|
|
|
|
|
|
An attempt was made to access a file in a way forbidden by its file access
|
|
|
|
permissions.
|
|
|
|
|
|
|
|
#### EADDRINUSE: Address already in use
|
|
|
|
|
|
|
|
An attempt to bind a server ([`net`][], [`http`][], or [`https`][]) to a local
|
|
|
|
address failed due to another server on the local system already occupying
|
|
|
|
that address.
|
|
|
|
|
|
|
|
#### ECONNREFUSED: Connection refused
|
|
|
|
|
|
|
|
No connection could be made because the target machine actively refused
|
|
|
|
it. This usually results from trying to connect to a service that is inactive
|
|
|
|
on the foreign host.
|
|
|
|
|
|
|
|
#### ECONNRESET: Connection reset by peer
|
|
|
|
|
|
|
|
A connection was forcibly closed by a peer. This normally results
|
|
|
|
from a loss of the connection on the remote socket due to a timeout
|
|
|
|
or reboot. Commonly encountered via the [`http`][] and [`net`][] modules.
|
|
|
|
|
|
|
|
#### EEXIST: File exists
|
|
|
|
|
|
|
|
An existing file was the target of an operation that required that the target
|
|
|
|
not exist.
|
|
|
|
|
|
|
|
#### EISDIR: Is a directory
|
|
|
|
|
|
|
|
An operation expected a file, but the given pathname was a directory.
|
|
|
|
|
|
|
|
#### EMFILE: Too many open files in system
|
|
|
|
|
|
|
|
Maximum number of [file descriptors][] allowable on the system has
|
|
|
|
been reached, and requests for another descriptor cannot be fulfilled until
|
|
|
|
at least one has been closed.
|
|
|
|
|
|
|
|
Commonly encountered when opening many files at once in parallel, especially
|
|
|
|
on systems (in particular, OS X) where there is a low file descriptor limit
|
|
|
|
for processes. To remedy a low limit, run `ulimit -n 2048` in the same shell
|
|
|
|
that will run the Node.js process.
|
|
|
|
|
|
|
|
#### ENOENT: No such file or directory
|
|
|
|
|
|
|
|
Commonly raised by [`fs`][] operations; a component of the specified pathname
|
|
|
|
does not exist -- no entity (file or directory) could be found by the given path.
|
|
|
|
|
|
|
|
#### ENOTDIR: Not a directory
|
|
|
|
|
|
|
|
A component of the given pathname existed, but was not a directory as expected.
|
|
|
|
Commonly raised by [`fs.readdir`][].
|
|
|
|
|
|
|
|
#### ENOTEMPTY: Directory not empty
|
|
|
|
|
|
|
|
A directory with entries was the target of an operation that requires
|
|
|
|
an empty directory -- usually [`fs.unlink`][].
|
|
|
|
|
|
|
|
#### EPERM: Operation not permitted
|
|
|
|
|
|
|
|
An attempt was made to perform an operation that requires appropriate
|
|
|
|
privileges.
|
|
|
|
|
|
|
|
#### EPIPE: Broken pipe
|
|
|
|
|
|
|
|
A write on a pipe, socket, or FIFO for which there is no process to read the
|
|
|
|
data. Commonly encountered at the [`net`][] and [`http`][] layers, indicative that
|
|
|
|
the remote side of the stream being written to has been closed.
|
|
|
|
|
|
|
|
#### ETIMEDOUT: Operation timed out
|
|
|
|
|
|
|
|
A connect or send request failed because the connected party did not properly
|
|
|
|
respond after a period of time. Usually encountered by [`http`][] or [`net`][] --
|
|
|
|
often a sign that a connected socket was not `.end()`'d appropriately.
|
|
|
|
|
|
|
|
[`Error`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
|
|
|
|
[`fs.readdir`]: fs.html#fs_fs_readdir_path_callback
|
|
|
|
[`fs.readFileSync`]: fs.html#fs_fs_readfilesync_file_options
|
|
|
|
[`fs.unlink`]: fs.html#fs_fs_unlink_path_callback
|
|
|
|
[`fs`]: fs.html
|
|
|
|
[`http`]: http.html
|
|
|
|
[`https`]: https.html
|
|
|
|
[`net`]: net.html
|
|
|
|
[`process.on('uncaughtException')`]: process.html#process_event_uncaughtexception
|
|
|
|
[`try / catch` construct]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
|
|
|
|
[`try { } catch(err) { }`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
|
|
|
|
[below]: #errors_error_propagation_and_interception
|
|
|
|
[domains]: domain.html
|
|
|
|
[event emitter-based]: events.html#events_class_events_eventemitter
|
|
|
|
[file descriptors]: https://en.wikipedia.org/wiki/File_descriptor
|
|
|
|
[online]: http://man7.org/linux/man-pages/man3/errno.3.html
|
|
|
|
[stream-based]: stream.html
|
|
|
|
[syscall]: http://man7.org/linux/man-pages/man2/syscall.2.html
|
|
|
|
[V8's stack trace API]: https://github.com/v8/v8/wiki/Stack-Trace-API
|
|
|
|
[vm]: vm.html
|