---
title: Bun v1.1.27
description: "Fixes 130 bugs (addressing 250 👍). `bun pm pack`, faster `node:zlib`. Static routes in Bun.serve(). ReadableStream support in response.clone() & request.clone(). Per-request timeouts. Cancel method in ReadableStream is called. `bun run` handles CTRL + C better. Faster buffered streams. `bun outdated` package filtering. Watch arbtirary file types in --hot and --watch. Fixes to proxies on Windows. Several Node.js compatibility improvements."
date: "2024-09-07T10:33:38.717Z"
author: chloe
---

Bun v1.1.27 is here! This release fixes 130 bugs (addressing 250 👍). `bun pm pack`, faster `node:zlib`. Static routes in Bun.serve(). ReadableStream support in response.clone() & request.clone(). Per-request timeouts. Cancel method in ReadableStream is called. `bun run` handles CTRL + C better. Faster buffered streams. `bun outdated` package filtering. Watch arbtirary file types in --hot and --watch. Fixes to proxies on Windows. Several Node.js compatibility improvements.

{% callout %}
We're hiring [systems engineers](/careers) in San Francisco to build the future of JavaScript!
{% /callout %}

#### To install Bun

{% codetabs %}

```sh#curl
$ curl -fsSL https://bun.sh/install | bash
```

```sh#npm
$ npm install -g bun
```

```sh#powershell
$ powershell -c "irm bun.sh/install.ps1|iex"
```

```sh#scoop
$ scoop install bun
```

```sh#brew
$ brew tap oven-sh/bun
$ brew install bun
```

```sh#docker
$ docker pull oven/bun
$ docker run --rm --init --ulimit memlock=-1:-1 oven/bun
```

{% /codetabs %}

#### To upgrade Bun

```sh
$ bun upgrade
```

## Native `node:zlib`

We rewrote `node:zlib` to use native code.

| Runtime      | node:zlib    | Stream (MB/s) | Sync (MB/s) |
| ------------ | ------------ | ------------- | ----------- |
| Bun v1.1.27  | `deflate`    | 32.79 MB/s    | 14.82 MB/s  |
| Node v22.5.1 | `deflate`    | 15.50 MB/s    | 31.39 MB/s  |
| Bun v1.1.26  | `deflate`    | 15.59 MB/s    | 10.29 MB/s  |
| Bun v1.1.27  | `deflateRaw` | 32.68 MB/s    | 14.60 MB/s  |
| Node v22.5.1 | `deflateRaw` | 19.77 MB/s    | 31.41 MB/s  |
| Bun v1.1.26  | `deflateRaw` | 15.67 MB/s    | 10.38 MB/s  |
| Bun v1.1.27  | `gunzip`     | 87.72 MB/s    | 107.60 MB/s |
| Bun v1.1.26  | `gunzip`     | 46.49 MB/s    | 42.74 MB/s  |
| Node v22.5.1 | `gunzip`     | 31.01 MB/s    | 75.86 MB/s  |
| Bun v1.1.27  | `gzip`       | 32.69 MB/s    | 14.91 MB/s  |
| Node v22.5.1 | `gzip`       | 18.46 MB/s    | 31.10 MB/s  |
| Bun v1.1.26  | `gzip`       | 15.29 MB/s    | 10.11 MB/s  |
| Bun v1.1.27  | `inflate`    | 87.79 MB/s    | 102.86 MB/s |
| Bun v1.1.26  | `inflate`    | 50.72 MB/s    | 43.83 MB/s  |
| Node v22.5.1 | `inflate`    | 26.07 MB/s    | 74.64 MB/s  |
| Bun v1.1.27  | `inflateRaw` | 87.68 MB/s    | 101.78 MB/s |
| Bun v1.1.26  | `inflateRaw` | 53.89 MB/s    | 43.13 MB/s  |
| Node v22.5.1 | `inflateRaw` | 33.35 MB/s    | 75.02 MB/s  |

Via a [third-party zlib benchmark](https://github.com/timotejroiko/zlib-benchmark) on a Linux x64 Hetzner server.

There's still more to do to optimize `node:zlib` in Bun, but this is a good start.

Big thanks to [@nektro](https://github.com/nektro) for implementing this.

## New command: `bun pm pack`

{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">In the next version of Bun<br><br>`bun pm pack` creates an npm package tarball for publishing or installing locally <a href="https://t.co/RdXdyzI3He">pic.twitter.com/RdXdyzI3He</a></p>&mdash; Bun (@bunjavascript) <a href="https://twitter.com/bunjavascript/status/1832386689182122092?ref_src=twsrc%5Etfw">September 7, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

{% /raw %}

`bun pm pack` is designed to be a drop-in replacement for `npm pack`.

## New in `Bun.serve()` (HTTP server)

This release introduces reliability and quality of life improvements to `Bun.serve()`, our fast HTTP server.

### Static routes

You can now pass a `static` option to serve static `Response` objects for a path.

```ts
Bun.serve({
  static: {
    "/api/health-check": new Response("🟢"),
    "/old-link": Response.redirect("/new-link", 301),
    "/api/version": Response.json(
      {
        app: require("./package.json").version,
        bun: Bun.version,
      },
      {
        headers: {
          "X-Powered-By": "bun",
        },
      },
    ),
  },

  async fetch(req) {
    return new Response("Dynamic!");
  },
});
```

### ReadableStream support in `request.clone()` and `response.clone()`

Cloning a streaming `Request` or `Response` is now supported via [`request.clone()`](https://developer.mozilla.org/en-US/docs/Web/API/Request/clone) and [`response.clone()`](https://developer.mozilla.org/en-US/docs/Web/API/Response/clone).

To clone a request from `Bun.serve`:

```ts
Bun.serve({
  async fetch(req, server) {
    const cloned = req.clone();
    await req.json();

    // Previously, this would be empty.
    await cloned.json();

    // ... rest of the code
  },
});
```

To clone a Response from `fetch`:

```ts
const response = await fetch("https://example.com");
const cloned = response.clone();

console.log(await response.text());
console.log(await cloned.text());
```

Previously, this was only supported for static responses like when passing a string, an ArrayBuffer, or a Blob to the `Response` constructor.

### The "cancel" method in ReadableStream

When a request is aborted, Bun now calls the `cancel` method in `ReadableStream` .

```ts
import { serve } from "bun";

serve({
  async fetch(req, server) {
    req.signal.addEventListener("abort", () => {
      // Previously, AbortSignal was the only way to detect if a request was aborted.
      console.log("Request aborted");
    });

    return new Response(
      new ReadableStream({
        async pull(controller) {
          controller.enqueue("Hello World");
          await Bun.sleep(1000);
        },
        cancel() {
          // New! Called when the request is aborted.
          console.log("Stream cancelled");
        },
      }),
    );
  },
});
```

### Per-request timeouts

The new `server.timeout(request: Request, seconds: number)` method allows you to set a timeout per specific HTTP request.

To set a 60 second timeout for a request:

```ts
Bun.serve({
  async fetch(req, server) {
    server.timeout(req, 60); // 60 seconds
    await req.formData();
    return new Response("Slow response");
  },
});
```

Thanks to [@cirospaciari](https://github.com/cirospaciari) for implementing this.

### Faster buffered streams

We didn't just add new features to `Bun.serve()` this release. We also made it faster.

{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">In the next version of Bun<br><br>The fast path in request.json() &amp; similar methods now works after accessing “.body”<br><br>New: 65,000 req/s<br>Prev: 29,000 req/s <a href="https://t.co/2EqYyCoq4G">pic.twitter.com/2EqYyCoq4G</a></p>&mdash; Jarred Sumner (@jarredsumner) <a href="https://twitter.com/jarredsumner/status/1830900845778743450?ref_src=twsrc%5Etfw">September 3, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

{% /raw %}

### New CLI flag: `--max-http-header-size`

Passing `--max-http-header-size` sets the size of the HTTP request header buffer.

https://github.com/oven-sh/bun/pull/13577

### Fixed: `server.requestIP` after `await`

Previously, using `server.requestIP` after a callback or call to `await` would lose the request metadata. This has been fixed.

```ts
Bun.serve({
  port: 3000,
  async fetch(req, server) {
    console.log(server.requestIP(req));
    // { address: '127.0.0.1', family: 'IPv4', ... }

    await req.formData();

    console.log(server.requestIP(req));
    //    now: { address: '127.0.0.1', family: 'IPv4', ... }
    // before: undefined
  },
});
```

### Fixed: `ws.publish` on a closed WebSocket

In `Bun.serve`, calling `.publish` on a websocket will send a message to all clients except the websocket itself. When using this in the `close` handler, the WebSocket was already closed and no message could be sent. This has now been fixed.

Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this.

### Fixed: memory leak when accessing request body and buffered methods

A memory leak has been fixed in code like the below:

```ts
Bun.serve({
  async fetch(req) {
    if (req.body) {
      await req.json();
    }

    // ... rest of the code
  },
});
```

When the `Request` body's `ReadableStream` was accessed, in certain cases a buffering method like `req.json` may use a different implementation and the `Request` object was incorrectly holding a strong reference to the `Promise` returned by `req.json` in those cases, leaking memory.

While adding clone() support for streams, we revised the implementation of `Request` and `Response` to fix this and similar issues.

## `bun outdated` filtering

`bun outdated` now has `--filter`, which allows you to choose which workspaces you want to audit for outdated packages.

```sh
# Path patterns:
# Matches all workspaces in `./packages`
$ bun outdated --filter="./packages/*"

# Name patterns:
# All workspaces with names starting with `pkg`
$ bun outdated --filter="pkg*"

# All workspaces excluding `pkg1`
$ bun outdated --filter="*" --filter="!pkg1"
```

Additionally, positional arguments filter the list of dependencies, which can be helpful if you only want to check certain packages for updates.

```sh
# All dependencies starting with `is-` (could display `is-even`, `is-odd`, ...)
$ bun outdated "is-*"

# All dependencies from a particular scope
$ bun outdated "@discordjs/*"

# With `--filter`. Matches all outdated `jquery` dependencies in all workspaces.
$ bun outdated jquery --filter="*"
```

## `bun run` Ctrl + C behavior is fixed

`bun run` wasn't propagating POSIX signals from the `bun` process to the child process (only from child -> parent). This led to strange bugs in certain cases, like CTRL + C not exiting the child process until later when an I/O error occurs from reading stdin on a disconnected terminal. This visually manifested as the `^[[A` character appearing when you press ↑ Up instead of the previous command.

This has been fixed.

{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">In the next version of Bun<br><br>A bug where the following would sometimes print `^[[A` is fixed<br>1. `bun run &lt;package.json script&gt;`<br>2. Ctrl + C<br>3. ↑ Up <a href="https://t.co/7YlR2knMLh">pic.twitter.com/7YlR2knMLh</a></p>&mdash; Jarred Sumner (@jarredsumner) <a href="https://twitter.com/jarredsumner/status/1831935501252882675?ref_src=twsrc%5Etfw">September 6, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

{% /raw %}

Thanks to [@xales](https://github.com/xales) for debugging this.

## Watch arbitrary file types in `--watch` and `--hot`

Bun's builtin watch & hot reloading now supports watching arbitrary file types.

To watch a file, import it.

```ts
import "./tailwind.css";
// ... rest of my app
```

Bun's watcher relies on the module graph to determine which files trigger a reload. This reduces unnecessary reloads, improving your iteration cycle time.

Previously, only JavaScript, TypeScript, JSON, TOML and .txt files were watched. Now, Bun will watch any file that is imported regardless of file extension.

### Fixed: Default `idleTimeout` no longer set in node:http

In Bun 1.1.26, the default `idleTimeout` was 10 seconds, which was a breaking change as versions before had unlimited timeout. The default value of `idleTimeout` is now `0`, which disables the timeout.

## Node.js compatibility improvements

This release also includes a number of Node.js compatibility improvements.

### Fixed: Crash while throwing an exception from N-API

A bug causing a crash in N-API when an exception was thrown has been fixed.

### Fixed: Crash in N-API when accessing heap-allocated JSValue

JavaScriptCore & V8 are different engines with different approaches to garbage collection. JavaScriptCore scans the stack. V8 relies on handle scopes.

Previously, Bun didn't implement handle scopes. This led to crashes in N-API packages like DuckDB that heap-allocate napi values without referencing them in stack memory. The garbage collector wouldn't see them, and clean up the memory prematurely.

Thanks to [@190n](https://github.com/190n) for implementing handle scopes.

### Fixed: Crash impacting Next.js middleware

A crash in `node:vm` when using a class extending a built-in class like `URL` or `Response` inside of `node:vm` has been fixed. This crash was reproducible in Next.js middleware.

### Fixed: Missing `ERR_INVALID_ARG_TYPE` in some `Buffer` methods

In `Buffer.isAscii` and `Buffer.isUtf8`, the error thrown when given invalid arguments now properly includes `code: "ERR_INVALID_ARG_TYPE"`.

### Fixed: Missing `ERR_INVALID_URL` in `new URL`

To match Node.js, the error thrown by `new URL` when giving an invalid URL now includes `code: "ERR_INVALID_URL"`

### Fixed: `AES-GCM` encryption of empty messages

Thanks to [@wpaulino](https://github.com/wpaulino), an empty message now properly round-trips in `AES-GCM` encryption.

### Fixed: `util.promisify` with `crypto.generateKeyPair`

Thanks to [@wpaulino](https://github.com/wpaulino), calling `util.promisify` on `crypto.generateKeyPair` will now return the proper promisified function.

### Fixed: Handling out-of-memory errors in `Buffer`

When converting a large string to a `Buffer`, Bun now handles out-of-memory errors by throwing an `OutOfMemoryError` instead of crashing.

### Fixed: `node:tls` accepting an arbitrary stream for a TLS socket. Fixed `mssql` package

The `tls.connect` function from `node:tls` accepts a `socket` option. This lets you upgrade any `net.Socket` to TLS. However, this parameter can actually be any arbitrary `stream.Duplex`, which Bun previously did not support, as it relies the underlying network connection to engage in TLS more efficiently.

This resolves the `mssql` package throwing `Error: socket must be an instance of net.Socket` when used.

Thanks to [@cirospaciari](https://github.com/cirospaciari)

### Fixed: `node:http` agent ignored

In certain cases, the `node:http` agent was not being used. This has been fixed.

Thanks to [@nektro](https://github.com/nektro)

### Fixed: `node:http` setTimeout & server.setTimeout ignored

With `server.timeout` now implemented, we've also added support for `server.setTimeout` and `request.setTimeout` in `node:http`.

Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this.

### Fixed: `node:vm` inconsistencies

Various subtle mistakes in `node:vm` have been fixed:

- `vm.runInThisContext` now operates in global context
- `script.runInNewContext` now operates in it's own context
- `script.runInThisContext` and `vm.runInThisContext` don't take context as an argument
- `vm.runInThisContext`, `vm.runInContext`, and `vm.runInContext` take a string as the options argument.

Thanks to [@SunsetTechuila](https://github.com/SunsetTechuila) for fixing these!

### Fixed: Missing `net.Socket.destroySoon`

Previously, this method in `node:net` was undefined. This is now fixed.

## fetch reliability improvements

### Proxies in fetch() on Windows work better now

On Windows, using a proxy with `fetch` often led to `error: Syscall` being thrown.

This has been resolved thanks to [@cirospaciari](https://github.com/cirospaciari).

### Fixed: a memory leak with `FormData` or `URLSearchParams` body

In Bun v1.1.25, a regression was introduced where sending `FormData` and `URLSearchParams` in the body of a `fetch()` request would leak memory. This regression is now fixed.

## Lots more fixes

### Fixed: Reading large files `Bun.file` was truncated

When reading a file over 4gb into a single `ArrayBuffer`, the buffer would be truncated to 4gb. This has now been fixed.

### Fixed: Clearing screen in some terminals

The ANSI escape code used to clear the terminal screen has been changed from `\x1b[H\x1b[2J` to `\x1B[2J\x1B[3J\x1B[H`, which is compatible with more terminals. Most notably, this fixes Visual Studio Code's terminal, which did not fully clear before this change.

Thanks to [@jakebailey](https://github.com/jakebailey) for fixing this.

### Fixed: Handling out-of-memory errors in `Bun.escapeHTML`

When giving large enough strings to `Bun.escapeHTML`, it will now throw an `OutOfMemoryError` instead of crashing.

### `Bun.deepEquals` performance improvements for `Map` and `Set`

After a the WebKit upgrade for Bun v1.1.19, the implementation of `Map` and `Set` changed to the point we had to remove their fast paths in `Bun.deepEquals`. Thanks to [@wpaulino](https://github.com/wpaulino), a new fast path has been added, which is better than what was previously in place.

Additionally, the fast path covers custom classes that extend `Map` or `Set`, giving them nearly indistinguishable performance in `Bun.deepEquals` from the base class itself.

### Fixed: `Failed to link package: EBUSY` on Windows

In bun install, an issue updating package binaries while they are currently open has been fixed

Thanks to [@dylan-conway](https://github.com/dylan-conway)

<!-- https://github.com/oven-sh/bun/pull/12750 -->

### Fixed: LCOV reporter properly reports non-hit lines

Bun's LCOV reporter previously would sometimes report `100%` line coverage when that wasnt always the case. This has now been fixed thanks to [@fmorency](https://github.com/fmorency).

### Fixed: `bun add -g` postinstall message

When installing a global package with a blocked postinstall script, the message will now include the correct command:

```diff
 $ bun install -g @delance/runtime
 bun add v1.1.27

 installed @delance/runtime@2024.8.103 with binaries:
  - delance-langserver

 68 packages installed [1.98s]

-Blocked 1 postinstall. Run `bun pm untrusted` for details.
+Blocked 1 postinstall. Run `bun pm -g untrusted` for details.
```

Thanks to [@RiskyMH](https://github.com/RiskyMH) for fixing this

### Fixed: Race condition in `Bun.build`

A race condition causing a `Bun.build` promise to hang has been fixed. This could be caused if you queued many `Bun.build` calls in a short period of time.

### Fixed: bun shell not keeping parent process alive

A bug where the following code would exit prematurely, wtihout printing "never reached!!! why!!" has been fixed.

```ts
import { $ } from "bun";
console.log("before shell");
(async function () {
  await `echo hi`;
  console.log("never reached!!! why!!");
})();
```

## Thanks to 17 contributors!

- [@17hz](https://github.com/17hz)
- [@190n](https://github.com/190n)
- [@xales](https://github.com/xales)
- [@nektro](https://github.com/nektro)
- [@RiskyMH](https://github.com/RiskyMH)
- [@fmorency](https://github.com/fmorency)
- [@wpaulino](https://github.com/wpaulino)
- [@mohit-s96](https://github.com/mohit-s96)
- [@Nanome203](https://github.com/Nanome203)
- [@jakebailey](https://github.com/jakebailey)
- [@sacsbrainz](https://github.com/sacsbrainz)
- [@jakeboone02](https://github.com/jakeboone02)
- [@cirospaciari](https://github.com/cirospaciari)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Marukome0743](https://github.com/Marukome0743)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@SunsetTechuila](https://github.com/SunsetTechuila)
