{"action":"created","issue":{"url":"https://api.github.com/repos/nodejs/promises/issues/10","repository_url":"https://api.github.com/repos/nodejs/promises","labels_url":"https://api.github.com/repos/nodejs/promises/issues/10/labels{/name}","comments_url":"https://api.github.com/repos/nodejs/promises/issues/10/comments","events_url":"https://api.github.com/repos/nodejs/promises/issues/10/events","html_url":"https://github.com/nodejs/promises/issues/10","id":133802245,"number":10,"title":"Differentiating Programmer Errors from Operational Errors","user":{"login":"chrisdickinson","id":37303,"avatar_url":"https://avatars.githubusercontent.com/u/37303?v=3","gravatar_id":"","url":"https://api.github.com/users/chrisdickinson","html_url":"https://github.com/chrisdickinson","followers_url":"https://api.github.com/users/chrisdickinson/followers","following_url":"https://api.github.com/users/chrisdickinson/following{/other_user}","gists_url":"https://api.github.com/users/chrisdickinson/gists{/gist_id}","starred_url":"https://api.github.com/users/chrisdickinson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chrisdickinson/subscriptions","organizations_url":"https://api.github.com/users/chrisdickinson/orgs","repos_url":"https://api.github.com/users/chrisdickinson/repos","events_url":"https://api.github.com/users/chrisdickinson/events{/privacy}","received_events_url":"https://api.github.com/users/chrisdickinson/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/nodejs/promises/labels/blocks-unflagging","name":"blocks-unflagging","color":"fbca04"},{"url":"https://api.github.com/repos/nodejs/promises/labels/concerns-error-symposium","name":"concerns-error-symposium","color":"fef2c0"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":60,"created_at":"2016-02-15T19:56:14Z","updated_at":"2016-02-16T19:22:17Z","closed_at":null,"body":"This primarily concerns the error symposium participants, but may also concern the post mortem WG.\r\n\r\n### The Problem\r\n\r\n* Promise users expect all Promise-returning API usage to return a Promise object, success or fail.\r\n* This means that invalid API use is returned as a rejection, alongside other errors.\r\n* This necessitates the use of `try / catch` in `async/await` code.\r\n* This also necessitates error type checking in promise-based code.\r\n  * Were a \"abort on unhandled rejection\" flag to land, this would reduce such a flags efficacy: given that such a flag would operate by attempting to immediately abort the promise at top of stack assuming no user-installed handlers were present, and given that in type-checking users would _usually_ add user-installed handlers.\r\n\r\n### Proposed Solutions\r\n\r\n#### Recovery Object\r\n\r\nAdd an optional object parameter to all promise-returning APIs. This will be known as the `recovery` object. It *does not change the behavior of Promises/A+*; it is purely a Node API-level pattern. It allows users to intercept errors before settling the returned promise, and change the outcome of the lower-level API call:\r\n\r\n```js\r\n// recovery object\r\nawait fs.readFilePromise('some/file', {\r\n  ENOENT() {\r\n    return null\r\n  }\r\n})\r\n\r\n// normal use:\r\nfs.readFilePromise('some/file')\r\n```\r\n\r\n**Pros:**\r\n\r\n* Promise API users get the API they expect. Error symposium users get the API they expect.\r\n* Simple to implement.\r\n\r\n**Cons:**\r\n\r\n* It's a new pattern.\r\n* It doesn't solve problems in the ecosystem.\r\n\r\n#### `--abort-on-sync-rejection`\r\n\r\nAdd a flag to abort the process on synchronous `new Promise` rejection. This does not extend to synchronous `throw` within `handlers`. Potentially patch `Promise.reject` so that it returns a pending promise that rejects on next tick.\r\n\r\nFor example, the following usage **would abort** under this flag:\r\n\r\n```js\r\nnew Promise(() => { throw new Error() })\r\nnew Promise((_, reject) => { reject(new Error()) })\r\n```\r\n\r\nThe following usage **would not** abort under this flag:\r\n\r\n```js\r\nnew Promise((_, reject) => { setTimeout(() => reject(new Error())) })\r\nattainPromise().then(() => { throw new Error() })\r\n```\r\n\r\nThe net effect being that the promise would immediately exit on invalid Node API use under this flag. Without the flag, the process keeps running \"as expected\" for the majority of promise users.\r\n\r\n**Pros:**\r\n\r\n* Solves problem in ecosystem for native promise users.\r\n* Does not introduce a new pattern.\r\n\r\n**Cons:**\r\n\r\n* Unclear on how common synchronous rejection is in `Promise` constructors. Believed to be uncommon, could be proven wrong?\r\n* Flagged and unflagged behavior diverge.\r\n\r\n### This Discussion\r\n\r\nPlease pose problems with or benefits of the listed solutions, **or** propose alternate avenues of inquiry which will be added to the issue text. Clarifying comments, like \"how are you using this?\" are in-scope. Comments that suggest that the desire to separate operational errors from programmer errors is invalid will be moderated in the interest of keeping this discussion productive. Thank you for participating!\r\n"},"comment":{"url":"https://api.github.com/repos/nodejs/promises/issues/comments/184840072","html_url":"https://github.com/nodejs/promises/issues/10#issuecomment-184840072","issue_url":"https://api.github.com/repos/nodejs/promises/issues/10","id":184840072,"user":{"login":"benjamingr","id":1315533,"avatar_url":"https://avatars.githubusercontent.com/u/1315533?v=3","gravatar_id":"","url":"https://api.github.com/users/benjamingr","html_url":"https://github.com/benjamingr","followers_url":"https://api.github.com/users/benjamingr/followers","following_url":"https://api.github.com/users/benjamingr/following{/other_user}","gists_url":"https://api.github.com/users/benjamingr/gists{/gist_id}","starred_url":"https://api.github.com/users/benjamingr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/benjamingr/subscriptions","organizations_url":"https://api.github.com/users/benjamingr/orgs","repos_url":"https://api.github.com/users/benjamingr/repos","events_url":"https://api.github.com/users/benjamingr/events{/privacy}","received_events_url":"https://api.github.com/users/benjamingr/received_events","type":"User","site_admin":false},"created_at":"2016-02-16T19:22:17Z","updated_at":"2016-02-16T19:22:17Z","body":"@markandrus the approach suggested in https://github.com/groundwater/nodejs-symposiums/pull/6 by @groundwater and @chrisdickinson is to check for a `.code` property for operational errors but it does not make the distinction based on the type alone.\r\n\r\nThis sounds like a reasonable path to explore - would you mind writing a concrete proposal based on it in a pull request?"}}