From 9537bca7a83b974e17a40f08f23e4f4427940526 Mon Sep 17 00:00:00 2001 From: Chris Dickinson <christopher.s.dickinson@gmail.com> Date: Tue, 10 Feb 2015 12:48:55 -0800 Subject: [PATCH 1/5] doc: add error documentation --- doc/api/_toc.markdown | 1 + doc/api/all.markdown | 1 + doc/api/errors.markdown | 448 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 450 insertions(+) create mode 100644 doc/api/errors.markdown diff --git a/doc/api/_toc.markdown b/doc/api/_toc.markdown index cf643e28cf98eb..c838ab383e2ed7 100644 --- a/doc/api/_toc.markdown +++ b/doc/api/_toc.markdown @@ -12,6 +12,7 @@ * [Debugger](debugger.html) * [DNS](dns.html) * [Domain](domain.html) +* [Errors](errors.html) * [Events](events.html) * [File System](fs.html) * [Globals](globals.html) diff --git a/doc/api/all.markdown b/doc/api/all.markdown index 0f0ec6338d8a50..c01752feed7cbf 100644 --- a/doc/api/all.markdown +++ b/doc/api/all.markdown @@ -11,6 +11,7 @@ @include dgram @include dns @include domain +@include errors @include events @include fs @include globals diff --git a/doc/api/errors.markdown b/doc/api/errors.markdown new file mode 100644 index 00000000000000..7b0fdad1d29c74 --- /dev/null +++ b/doc/api/errors.markdown @@ -0,0 +1,448 @@ +# 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 client may **intercept** +the error. Exceptions can be intercepted using the `try / catch` construct; +other propagation strategies are covered [below](#errors_error_propagation_and_interception). + +## 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 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](https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi). +Stack traces only extend to the beginning of synchronous code execution, *or* a number of frames given by +`Error.stackTraceLimit`, whichever is smaller. + +#### 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. +* `/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). + +#### Error.captureStackTrace(targetObject) + +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()`. + +#### 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 effect 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 +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 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 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 +that is not defined. Most commonly it indicates a typo, or an otherwise broken program. +Only V8 may generate and propagate these errors. + +```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](vm.html). 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. + +### 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 inherit from +`Error`, all exceptions thrown by Node 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` on most Unices; +or [online](http://man7.org/linux/man-pages/man2/intro.2.html). + +In Node, system errors are represented as augmented Error objects -- not full +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 + +A string representing the error code, which is always `E` followed by capital +letters, and may be referenced in `man 2 intro`. + +### Common System Errors + +This list is **not exhaustive**, but enumerates many of the common system errors when +writing a Node program. An exhaustive list may be found [here](http://man7.org/linux/man-pages/man2/intro.2.html). + +#### EPERM: Operation not permitted + +An attempt was made to perform an operation that requires appropriate +privileges. + +#### ENOENT: No such file or directory + +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. + +#### EACCES: Permission denied + +An attempt was made to access a file in a way forbidden by its file access +permissions. + +#### 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. + +#### EMFILE: Too many open files in system + +Maxiumum number of [file descriptors](http://en.wikipedia.org/wiki/File_descriptor) 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 process. + +#### 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](net.html) and [http](http.html) layers, indicative that +the remote side of the stream being written to has been closed. + +#### EADDRINUSE: Address already in use + +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. + +#### 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. + +#### 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. + +#### ENOTEMPTY: Directory not empty + +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). + +#### ETIMEDOUT: Operation timed out + +An 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 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 -- even user created event emitters and streams will throw +errors when no error handlers are attached. An example: + +```javascript +var events = require('events'); + +var ee = new events.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. From 7e553255e3aa25f0a06b4cd12fde7878348d465b Mon Sep 17 00:00:00 2001 From: Chris Dickinson <christopher.s.dickinson@gmail.com> Date: Tue, 10 Feb 2015 13:21:08 -0800 Subject: [PATCH 2/5] address @trevnorris' comments --- doc/api/errors.markdown | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/doc/api/errors.markdown b/doc/api/errors.markdown index 7b0fdad1d29c74..6c32d3ae9d7c60 100644 --- a/doc/api/errors.markdown +++ b/doc/api/errors.markdown @@ -14,7 +14,7 @@ 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 client may **intercept** +**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](#errors_error_propagation_and_interception). @@ -119,7 +119,7 @@ loop tick. System-level errors are generated as augmented Error instances, which are detailed [below](#errors_system_errors). -#### Error.captureStackTrace(targetObject) +#### 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` @@ -136,6 +136,27 @@ 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 @@ -176,10 +197,11 @@ of argument validation. 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. -Only V8 may generate and propagate these errors. +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. +doesNotExist; // throws ReferenceError, doesNotExist is not a variable in this program. ``` ReferenceError instances will have an `.arguments` member that is an array containing From 17929bda98ce69e0ee63f2c49c8d26448da599c6 Mon Sep 17 00:00:00 2001 From: Chris Dickinson <christopher.s.dickinson@gmail.com> Date: Tue, 10 Feb 2015 13:23:34 -0800 Subject: [PATCH 3/5] node -> io.js --- doc/api/errors.markdown | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/api/errors.markdown b/doc/api/errors.markdown index 6c32d3ae9d7c60..6c50f6b934d373 100644 --- a/doc/api/errors.markdown +++ b/doc/api/errors.markdown @@ -2,7 +2,7 @@ <!--type=misc--> -Errors generated by Node.js fall into two categories: JavaScript errors and system +Errors generated by io.js fall into two categories: JavaScript errors and system errors. All errors inherit from or are instances of JavaScript's [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) class and are guaranteed to provide *at least* the attributes available on that class. @@ -34,7 +34,7 @@ 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 will generate this class of error to encapsulate system +**Note**: io.js will generate this class of error to encapsulate system errors as well as plain JavaScript errors. #### new Error(message) @@ -106,7 +106,7 @@ makeFaster(); // will throw: 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. +* `plain-filename.js:line:column`, if the frame represents a call internal to io.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 @@ -177,7 +177,7 @@ range, or outside the set of options for a given function parameter. An example: require('net').connect(-1); // throws RangeError, port should be > 0 && < 65536 ``` -Node will generate and throw RangeError instances *immediately* -- they are a form +io.js will generate and throw RangeError instances *immediately* -- they are a form of argument validation. ### Class: TypeError @@ -190,7 +190,7 @@ be considered a TypeError. require('url').parse(function() { }); // throws TypeError, since it expected a string ``` -Node will generate and throw TypeError instances *immediately* -- they are a form +io.js will generate and throw TypeError instances *immediately* -- they are a form of argument validation. ### Class: ReferenceError @@ -244,7 +244,7 @@ by other contexts. 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 inherit from -`Error`, all exceptions thrown by Node or the JavaScript runtime *will* be instances of Error. +`Error`, all exceptions thrown by io.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. @@ -257,7 +257,7 @@ 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` on most Unices; or [online](http://man7.org/linux/man-pages/man2/intro.2.html). -In Node, system errors are represented as augmented Error objects -- not full +In io.js, system errors are represented as augmented Error objects -- not full subclasses, but instead an error instance with added members. ### Class: System Error @@ -275,7 +275,7 @@ letters, and may be referenced in `man 2 intro`. ### Common System Errors This list is **not exhaustive**, but enumerates many of the common system errors when -writing a Node program. An exhaustive list may be found [here](http://man7.org/linux/man-pages/man2/intro.2.html). +writing a io.js program. An exhaustive list may be found [here](http://man7.org/linux/man-pages/man2/intro.2.html). #### EPERM: Operation not permitted @@ -315,7 +315,7 @@ 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 process. +that will run the io.js process. #### EPIPE: Broken pipe @@ -356,7 +356,7 @@ often a sign that a connected socket was not `.end()`'d appropriately. <!--type=misc--> -All Node APIs will treat invalid arguments as exceptional -- that is, if passed +All io.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. @@ -450,7 +450,7 @@ connection.pipe(process.stdout); ``` The "throw when no error handlers are attached behavior" is not limited to APIs -provided by node -- even user created event emitters and streams will throw +provided by io.js -- even user created event emitters and streams will throw errors when no error handlers are attached. An example: ```javascript From 666e62ca03b718fe20aed150649b0111edf0d0e7 Mon Sep 17 00:00:00 2001 From: Chris Dickinson <christopher.s.dickinson@gmail.com> Date: Tue, 10 Feb 2015 13:31:22 -0800 Subject: [PATCH 4/5] fix outdated link --- doc/api/errors.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/errors.markdown b/doc/api/errors.markdown index 6c50f6b934d373..ddc7a02ba71460 100644 --- a/doc/api/errors.markdown +++ b/doc/api/errors.markdown @@ -41,7 +41,7 @@ errors as well as plain JavaScript errors. 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](https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi). +was called. Stack traces are subject to [V8's stack trace API](https://code.google.com/p/v8-wiki/wiki/JavaScriptStackTraceApi). Stack traces only extend to the beginning of synchronous code execution, *or* a number of frames given by `Error.stackTraceLimit`, whichever is smaller. From 553243d1be57d661d63b6e3a2ad1680a10bcceea Mon Sep 17 00:00:00 2001 From: Chris Dickinson <christopher.s.dickinson@gmail.com> Date: Tue, 10 Feb 2015 13:44:32 -0800 Subject: [PATCH 5/5] fix typo --- doc/api/errors.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/errors.markdown b/doc/api/errors.markdown index ddc7a02ba71460..92cae6d256d616 100644 --- a/doc/api/errors.markdown +++ b/doc/api/errors.markdown @@ -348,7 +348,7 @@ an empty directory -- usually [fs.unlink](fs.html#fs_fs_unlink_path_callback). #### ETIMEDOUT: Operation timed out -An connect or send request failed because the connected party did not properly +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.