# bun/no-unhandled-emitter-errors

> Require an `error` listener on event emitters that Node.js functions return

When an event emitter emits `error` and nobody listens for it, the error is thrown instead. A `try` around the call doesn't catch it, because it happens later. So `spawn("gti")` with a typo, or `createReadStream()` on a file that's gone, ends the whole process.

The rule looks at what these functions return:

| Module | Functions |
| --- | --- |
| `node:child_process` | `spawn`, `fork` |
| `node:cluster` | `fork` |
| `node:fs` | `createReadStream`, `createWriteStream`, `watch` |
| `node:http`, `node:https` | `request`, `get` |
| `node:http2`, `node:tls` | `connect` |
| `node:net` | `connect`, `createConnection` |

{/* Generated by src/codegen/lint-rule-docs.ts. Do not edit this section. */}

## Configure

Off by default. To turn it on:

```toml bunfig.toml
[lint.rules]
"bun/no-unhandled-emitter-errors" = "error" # or "warn"
```

Every option, set to its default:

```toml bunfig.toml
[lint.rules]
"bun/no-unhandled-emitter-errors" = ["error", {
  factories = [], # list of objects
}]
```

{/* End of the generated section. */}

## Examples

Reported:

{/* bad */}
```js
import { spawn } from "node:child_process";

const child = spawn("git", ["status", "--short"]);
child.stdout.on("data", show);
child.on("exit", done);
```

`pipe()` doesn't pass errors on, so the source still needs a listener:

{/* bad */}
```js
import { createReadStream } from "node:fs";

createReadStream(file).pipe(response);
```

Not reported:

{/* good */}
```js
import { spawn } from "node:child_process";

const child = spawn("git", ["status", "--short"]);
child.stdout.on("data", show);
child.on("exit", done);
child.on("error", fail);
```

{/* good */}
```js
import { createReadStream } from "node:fs";

createReadStream(file).on("error", fail).pipe(response);
```

An emitter that's returned, exported or passed to another function isn't reported, because the listener might be added there. `pipeline()` handles its streams' errors:

{/* good */}
```js
import { createReadStream } from "node:fs";
import { pipeline } from "node:stream/promises";

await pipeline(createReadStream(file), response);

export function open(path) {
  return createReadStream(path);
}

export const log = createReadStream("app.log");
```

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `factories` | `[]` | More functions that return an emitter, checked in addition to the table above. Each entry is `{ module, names }`, with the import specifier and the function names. Without `names`, the default export is the function. |

```toml bunfig.toml
[lint.rules]
"bun/no-unhandled-emitter-errors" = ["error", {
  factories = [{ module = "ws", names = ["createWebSocketStream"] }],
}]
```

{/* bad {"options": [{"factories": [{"module": "ws", "names": ["createWebSocketStream"]}]}]} */}
```js
import { createWebSocketStream } from "ws";

const stream = createWebSocketStream(socket);
stream.on("data", show);
```
