@ -18,6 +18,123 @@ The style of API called determines how generated errors are handed back, or
the error. Exceptions can be intercepted using the `try / catch` construct;
other propagation strategies are covered [below ](#errors_error_propagation_and_interception ).
## 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 ](fs.html#fs_fs_readfilesync_filename_options )) 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 ](stream.html ) and [event emitter-based ](events.html#events_class_events_eventemitter ) 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 ](domain.html ) are
employed appropriately or [process.on('uncaughtException') ](process.html#process_event_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 ](domain.html ) 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 -->
@ -45,6 +162,54 @@ was called. Stack traces are subject to [V8's stack trace API](https://code.goog
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
@ -119,54 +284,6 @@ loop tick.
System-level errors are generated as augmented Error instances, which are detailed
[below ](#errors_system_errors ).
#### 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.
### Class: RangeError
A subclass of Error that indicates that a provided argument was not within the
@ -180,19 +297,6 @@ 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: 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.
### Class: ReferenceError
A subclass of Error that indicates that an attempt is being made to access a variable
@ -238,6 +342,19 @@ try {
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 -->
@ -262,46 +379,49 @@ subclasses, but instead an error instance with added members.
### Class: System Error
#### error.syscall
A string representing the [syscall ](http://man7.org/linux/man-pages/man2/syscall.2.html ) that failed.
#### error.errno
#### 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 ](http://man7.org/linux/man-pages/man2/syscall.2.html ) 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 ](http://man7.org/linux/man-pages/man3/errno.3.html ).
#### EPERM: Operation not permitt ed
#### EACCES: Permission deni ed
An attempt was made to perform an operation that requires appropriate
privilege s.
An attempt was made to access a file in a way forbidden by its file access
permission s.
#### ENOENT: No such file or directory
#### EADDRINUSE: Address already in use
Commonly raised by [fs ](fs.html ) operations; a component of the specified pathname
does not exist -- no entity (file or directory) could be found by the given path.
An attempt to bind a server ([net](net.html), [http ](http.html ), or [https ](https.html )) to a local
address failed due to another server on the local system already occupying
that address.
#### EACCES: Permission deni ed
#### ECONNREFUSED: Connection refus ed
An attempt was made to access a file in a way forbidden by its file access
permissions.
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 ](http.html ) and [net ](net.html ) modules.
#### EEXIST: File exists
An existing file was the target of an operation that required that the target
not exist.
#### ENOTDIR: Not a directory
A component of the given pathname existed, but was not a directory as expected.
Commonly raised by [fs.readdir ](fs.html#fs_fs_readdir_path_callback ).
#### EISDIR: Is a directory
An operation expected a file, but the given pathname was a directory.
@ -317,154 +437,34 @@ 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.
#### EPIPE: Broken pipe
#### ENOENT: No such file or directory
A write on a pipe, socket, or FIFO for which there is no process to read the
data. Commonly encountered at the [net ](net.html ) and [http ](http.html ) layers, indicative that
the remote side of the stream being written to has been closed.
Commonly raised by [fs ](fs.html ) operations; a component of the specified pathname
does not exist -- no entity (file or directory) could be found by the given path.
#### EADDRINUSE: Address already in use
#### ENOTDIR: Not a directory
An attempt to bind a server ([net](net.html), [http ](http.html ), or [https ](https.html )) to a local
address failed due to another server on the local system already occupying
that address.
A component of the given pathname existed, but was not a directory as expected.
Commonly raised by [fs.readdir ](fs.html#fs_fs_readdir_path_callback ).
#### ECONNRESET: Connection reset by peer
#### ENOTEMPTY: Directory not empty
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 ](http.html ) and [net ](net.html ) modules.
A directory with entries was the target of an operation that requires
an empty directory -- usually [fs.unlink ](fs.html#fs_fs_unlink_path_callback ).
#### ECONNREFUSED: Connection refus ed
#### EPERM: Operation not permitt ed
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.
An attempt was made to perform an operation that requires appropriate
privileges.
#### ENOTEMPTY: Directory not empty
#### EPIPE: Broken pipe
A directory with entries was the target of an operation that requires
an empty directory -- usually [fs.unlink ](fs.html#fs_fs_unlink_path_callback ).
A write on a pipe, socket, or FIFO for which there is no process to read the
data. Commonly encountered at the [net ](net.html ) and [http ](http.html ) 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 ](http.html ) or [net ](net.html ) --
often a sign that a connected socket was not `.end()` 'd appropriately.
## 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 ](fs.html#fs_fs_readfilesync_filename_options )) 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.
### 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 ](domain.html ) are enabled, they may intercept the thrown error; similarly, if a
handler has been added to `process.on('uncaughtException')` , it will intercept
the error.
### Error events
<!-- type=misc -->
The other mechanism for providing errors is the "error" event. This is
typically used by [stream-based ](stream.html ) and [event emitter-based ](events.html#events_class_events_eventemitter ) 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 ](domain.html ) are
employed appropriately or [process.on('uncaughtException') ](process.html#process_event_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.