---
title: Bun v1.1.22
description: "Fixes 79 bugs (addressing 93 👍). Express is now 3x faster in Bun, ES modules load faster on Windows, 10% faster Bun.serve() at POST requests, source maps in `bun build --compile`. Memory usage reductions to `--hot`, Bun.serve(), and imports. `Uint8Array.toBase64()`, `Uint8Array.toHex()`, and lots of Node.js compatibiltiy improvements and bugfixes."
date: "2024-08-07T22:01:19.122Z"
author: ashcon
---

Bun v1.1.22 is here! This release fixes 79 bugs (addressing 93 👍). Express is now 3x faster in Bun, ES modules load faster on Windows, 10% faster Bun.serve() at POST requests, source maps in `bun build --compile`. Memory usage reductions to `--hot`, Bun.serve(), and imports. `Uint8Array.toBase64()`, `Uint8Array.toHex()`, and lots of Node.js compatibiltiy improvements and bugfixes.

{% 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
```

## Express is now 3x faster in Bun

In this release, we made performance and compatibility improvements to Bun's `node:http` implementation. This increased `express` request throughput by 50% compared to Bun v1.1.21, which means its 3x faster in Bun than Node.js running the same code.

![](https://github.com/user-attachments/assets/f96ad9dc-7957-4073-8057-60e130824d28)

## ES Modules load up to 4x faster on Windows

To make running TypeScript, JSX, ES modules, and CommonJS all just work in Bun, we transpile every file on the fly. This inherently has a performance cost.

This release brings concurrent transpilation support to Bundows, which makes loading ES modules faster.

```js
async function benchmark(name) {
  console.time(name);
  await import(name);
  console.timeEnd(name);
}

await benchmark("lodash-es");
```

In this benchmark, we're running the above code and measuring the time it to import a popular package, like `lodash-es`.

| Runtime         | Time (ms) |
| --------------- | --------- |
| Bun v1.1.22     | 39        |
| Bun v1.1.21     | 82        |
| Node.js v22.4.1 | 186       |

This optimization previously was only supported on Bun for Linux & macOS, but now it is also supported on Windows.

## 10% higher throughput POST requests in `Bun.serve()`

If you code does not read the body of an incoming `Request`, there is a 10% performance improvement from the last release of Bun.

{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">In the next version of Bun<br><br>Bun.serve() gets 10% higher req/s on POST requests that ignore the body. <a href="https://t.co/OxkIGwYaWn">pic.twitter.com/OxkIGwYaWn</a></p>&mdash; Bun (@bunjavascript) <a href="https://twitter.com/bunjavascript/status/1818590757118525457?ref_src=twsrc%5Etfw">July 31, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
{% /raw %}

## Less memory usage

### `bun --hot` uses less memory

In this release, Bun uses 2x less memory when you use `bun --hot` to reload code.

{% raw %}

<blockquote class="twitter-tweet" data-media-max-width="560"><p lang="en" dir="ltr">In the next version of Bun<br><br>bun --hot uses less memory after many runs<br><br>left: Bun v1.1.22 (new)<br>right: Bun v1.1.21 (old) <a href="https://t.co/eDl5iqZsme">pic.twitter.com/eDl5iqZsme</a></p>&mdash; Jarred Sumner (@jarredsumner) <a href="https://twitter.com/jarredsumner/status/1818918642022858847?ref_src=twsrc%5Etfw">August 1, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

{% /raw %}

Previously, we were not always releasing the source code for old versions of modules. This also applies if your code or dependencies modifies [`require.cache`](https://nodejs.org/api/modules.html#requirecache), which is a common pattern for reloading code.

### Importing modules that are garbage collected uses less memory

We fixed a bug where importing or requiring a module that is garbage collected would keep a reference to that module's source code.

This was also caused when a module would throw an error, which would keep a reference to the module's source code.

{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">In the next version of Bun<br><br>require()&#39;ing or import&#39;ing large modules that throw an error uses less memory <a href="https://t.co/ruMqFNDzqM">pic.twitter.com/ruMqFNDzqM</a></p>&mdash; Jarred Sumner (@jarredsumner) <a href="https://twitter.com/jarredsumner/status/1818932723664535928?ref_src=twsrc%5Etfw">August 1, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

{% /raw %}

### Memory reductions

We also patched various memory leaks, including when:

- requiring a CommonJS module
- computing line offsets in source maps
- transpiling more than 64 files, concurrently
- creating a large number of `setTimeout()` or `setInterval()` timers

## Better stack traces

We fixed a bug in how `error.stack` traces are rendered in Bun. Sometimes the source URL of a call site would be empty, which would cause the stack trace to be slightly different than what most tools expect to receive. Now, Next.js renders stack traces properly.

{% raw %}

<div style="display: flex; align-items: center; justify-content: space-between; gap: 1rem;">
  <img src="https://github.com/user-attachments/assets/1600f9c9-5076-4708-9e1a-34e949d903bb" style="width: 50%;">
  <img src="https://github.com/user-attachments/assets/0fd5eadf-b0d4-4c4b-ad21-a48c1ff74b84" style="width: 50%;">
</div>

<div style="display: flex; align-items: center; justify-content: space-between; gap: 1rem;">
  <figcaption>Before: Stack traces do not render in Next.js.</figcaption>
  <figcaption>After: Stack traces show the correct source in Next.js.</figcaption>
</div>

{% /raw %}

## Sourcemaps in single-file executables

`bun build --compile` lets you generate a [single-file executable](/docs/bundler/executables) that bundles your source code, dependencies, and Bun into a single file you can deploy to production without needing other dependencies.

In this release of Bun, `--sourcemap` is now properly supported in single-file executables. This gives you better stack traces for debugging.

```sh
$ bun build cli.ts --compile --sourcemap
```

Before:

```ts
/tmp
❯ bun-1.1.21 build --compile --sourcemap errory.ts
[3ms] bundle 1 modules
[110ms] compile errory

/tmp
❯ ./errory
2 | // @bun
3 | // errory.ts
4 | throw new Error("hey " + n);
^
error: hey 42
at hey (/$bunfs/root/errory:4:9)
      at /$bunfs/root/errory:6:4

Bun v1.1.21 (macOS arm64)
```

After:

```ts
❯ bun build  --compile --sourcemap errory.ts
   [1ms]  bundle  1 modules
 [101ms] compile  errory

/tmp
❯ ./errory
1 | function hey(n: number) {
2 |   throw new Error("hey " + n);
            ^
error: hey 42
      at hey (errory.ts:2:9)
      at errory.ts:4:1

Bun v1.1.22-canary.104+c527058f1 (macOS arm64)
```

To reduce the memory and file-size cost of sourcemaps, we compress the input source code with `zstd` and serialize into a custom binary format.

## Node.js compatibility

### `util.getSystemErrorName()`

Bun now supports the [`util.getSystemErrorName()`](https://nodejs.org/api/util.html#utilgetsystemerrornameerr) function from the `node:util` module. This allows you to return the name of the error code for an error object.

```js
import { readFileSync } from "node:fs";
import { getSystemErrorName } from "node:util";

try {
  readFileSync("/does/not/exist");
} catch (error) {
  console.log(getSystemErrorName(error)); // "ENOENT"
}
```

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

### `util.aborted()`

Bun now supports the [`util.aborted()`](https://nodejs.org/api/util.html#utilabortedsignal-resource) function from the `node:util` module. This allows you to listen to an `AbortSignal` and receive a promise that resolves when the signal is aborted.

```js
import { aborted } from "node:util";

const controller = new AbortController();
const promise = aborted(controller.signal);

promise.then(() => {
  console.log("Aborted!");
});
```

### `events.getEventListeners()`

Bun also now supports the [`events.getEventListeners()`](https://nodejs.org/api/events.html#eventsgeteventlistenersemitterortarget-eventname) function for `EventTarget` objects from the `node:events` module. This allows you to get all listeners for a given event name on a given emitter.

```js
import { getEventListeners } from "node:events";

const emitter = new EventTarget();
emitter.addEventListener("foo", function foo() {});

console.log(getEventListeners(emitter, "foo"));
// [ [Function: foo] ]
```

Previously, this was only supported for `EventEmitter` objects from the `node:events` module.

### `NODE_EXTRA_CA_CERTS`

Bun now supports the [`NODE_EXTRA_CA_CERTS`](https://nodejs.org/api/cli.html#node_extra_ca_certsfile) environment variable, which allows you to specify a file containing one or more CA certificates to use when verifying TLS certificates. This works for the runtime, `bun install`, and everything else in Bun that makes HTTPS requests.

```sh
$ NODE_EXTRA_CA_CERTS=ca.pem bun install
$ NODE_EXTRA_CA_CERTS=another.pem bun run script.ts
```

### Fixed: Support async interators in `fs.promises.writeFile()`

Node.js has [undocumented](https://github.com/nodejs/node/blob/2eff28fb7a93d3f672f80b582f664a7c701569fb/lib/internal/fs/promises.js#L481-L493) support for async iterators in `fs.promises.writeFile()`. This was relied upon by various packages, and we decided to support it in Bun.

```js
import { writeFile } from "node:fs/promises";

const iterator = async function* () {
  yield "Hello";
  yield "World";
};
await writeFile("hello.txt", iterator);
```

### Fixed: Bun now exits with `1` if `process.on("exit")` throws

We fixed a bug where Bun would not propagate the right exit code if the `exit` or `beforeExit` event listeners threw an error.

```js
process.on("exit", () => {
  throw new Error("Oh no!");
});
```

This has been fixed thanks to [@nektro](https://github.com/nektro)!

### Fixed: `Worker` constructor would misinterpret `eval` property

There was a bug where the `Worker` constructor would misinterpret the `eval` property, when being explicitly defined. This was a regression that was introduced in Bun v1.1.13, and has now been fixed.

```js
const worker = new Worker("console.log('hello!')", { eval: false });

// Before: hello!
// After: BuildMessage: ModuleNotFound
```

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

### Fixed: `os.freemem()` now works on macOS

This was previously already implemented on Linux and Windows so this API now works on all platforms.

This has been fixed thanks to [@nektro](https://github.com/nektro)!

## Web APIs

### `Uint8Array.toBase64()`

Bun now has support for base64 encoding and decoding methods on `Uint8Array`. This was implemented in WebKit, which followed the TC39 stage 3 [proposal](https://github.com/tc39/proposal-arraybuffer-base64) for these additions.

- `Uint8Array.prototype.toBase64()` converts a `Uint8Array` to a base64 string
- `Uint8Array.prototype.fromBase64()` converts a base64 string to a `Uint8Array`

```js
new Uint8Array([1, 2, 3, 4, 5]).toBase64(); // "AQIDBA=="
Unit8Array.fromBase64("AQIDBA=="); // [1, 2, 3, 4, 5]
```

These are Web standard alternatives to ubiquitous the `Buffer.prototype.toString("base64")` and `Buffer.from(string, "base64")` patterns in Node.js.

### `Uint8Array.toHex()`

These methods were also added for converting `Uint8Array` to and from hex strings.

- `Uint8Array.prototype.toHex()` converts a `Uint8Array` to a hex string
- `Uint8Array.prototype.fromHex()` converts a hex string to a `Uint8Array`

```js
new Uint8Array([1, 2, 3, 4, 5]).toHex(); // "0102030405"
Unit8Array.fromHex("0102030405"); // [1, 2, 3, 4, 5]
```

Thanks to [@dcrousso](https://x.com/dcrousso) and [@constellation](https://x.com/constellation) for implementing these features in WebKit!

## `bun build`

### Converting `require.main === module` to `import.meta.main`

Previously, using `require.main === module` would mark the module as CommonJS (since it uses `module`). Now, Bun rewrites this into `import.meta.main`, meaning you can use this pattern alongside import statements.

```js
import * as fs from "fs";

if (typeof require !== "undefined" && require.main === module) {
  console.log("main!", fs);
}
```

```js
1 | import "fs";
           ^
error: Cannot use import statement with CommonJS-only features
    at /index.js:1:8

note: Try require("fs") instead
note: This file is CommonJS because 'module' was used
```

This also fixes support for `require.main === module` in single-file executables using CommonJS modules and `bun build --compile`.

Thanks to [@paperclover](https://github.com/paperclover) for implementing these features!

### `--ignore-dce-annotations`

Some JavaScript tools support special annotations that can influence during dead-code elimination. For example, the `@__PURE__` annotation tells bundlers that a function call is pure (regardless of if it actually is), and that the call can be removed if it is not used.

```js
let button = /* @__PURE__ */ React.createElement(Button, null);
```

Bundling or running the above code will result in an empty file, since the `button` variable is not used.

Sometimes, a library may include incorrect annotations, which can cause Bun to remove side effects which were needed. To workaround these issue, you can use the `--ignore-dce-annotations` flag when running `bun build` to ignore all annotations. This should only be used if dead-code elimination breaks bundles, and fixing the annotations should be preferred to leaving this flag on.

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

### Fixed: Assignment to `module.exports` in bundles

When bundling CommonJS modules, Bun tries to convert `module.exports` into `exports` if possible. This helps minification, but assigning to either `module.exports` or `exports` must undo optimization. This did not happen for instances of `module.exports` textually before the assignment, which is important for functions.

```ts#input.ts
function main() {
  console.log(module.exports);
}
module.exports = 123;
main();
```

```js#out.js
 var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);

 // input.ts
 var require_input = __commonJS((exports, module) => {
   function main() {
-    console.log(exports);
+    console.log(module.exports);
   }
   module.exports = 123;
   main();
 });
 export default require_input();
```

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

### Fixed: Minifying `await import("react-dom/server")`

A bug causing the following error when using `--minify-identifier` on a package that dynamically imports `react-dom` has been fixed:

```js
SyntaxError: Cannot declare an imported binding name twice
```

For some packages like React, Bun applies extra optimizations to convert CommonJS into ESM. In this conversion, the generated import statements had the wrong scope assigned, causing the minifier to two import statements the same minified variable name.

## Fixed bugs

We spend a lot of time fixing bugs in Bun. That's because our top priority is to support Bun in production.

{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">We fixed 180 bugs in July <a href="https://t.co/KwXyZy9sTG">pic.twitter.com/KwXyZy9sTG</a></p>&mdash; Bun (@bunjavascript) <a href="https://twitter.com/bunjavascript/status/1819466793779638782?ref_src=twsrc%5Etfw">August 2, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
{% /raw %}

If you experience a bug that we haven't fixed, please file an issue or upvote an existing issue on GitHub so we can prioritize it. It helps if you are able to provide a minimal reproducible example.

### Missing preview with uncaught error in `Bun.serve()`

When you pass `development: true` to `Bun.serve()`, we enable a builtin error handler that shows a preview of the error when an uncaught exception is thrown in the handler.

We fixed a bug where the error preview would not be shown if an uncaught exception was thrown in `Bun.serve()`. This was a regression that was introduced in Bun v1.1.9, and has now been fixed.

{% raw %}

<div style="display: flex; align-items: center; justify-content: space-between; gap: 1rem;">
  <img src="https://github.com/user-attachments/assets/f912489d-9fb1-41c0-8853-bb7749a3674c" style="width: 50%;">
  <img src="https://github.com/user-attachments/assets/efda2df3-b3be-40bb-9d9e-b24027b8b008" style="width: 50%;">
</div>

<div style="display: flex; align-items: center; justify-content: space-between; gap: 1rem;">
  <figcaption>Before: Error is missing</figcaption>
  <figcaption>After: Error and stack trace is shown</figcaption>
</div>

{% /raw %}

### `TextDecoder` not properly decoding 192 or 193 correctly

We fixed a bug where `TextDecoder` would not properly decode UTF-8 sequences that started with `192` or `193`.

```js
const decoder = new TextDecoder();
const bytes = new Uint8Array([192, 191]);

console.log(decoder.decode(bytes));
// Before: "?"
// After: "\uFFFD\uFFFD"
```

### Non-ASCII template literals with addition operator

We fixed a transpiler bug where template literals with an addition operator and non-ASCII input would not be transpiled correctly in certain cases. This was a regression that was introduced in Bun v1.1.17.

```js
console.log(`${123}➖` + "123456 456");
// Before: 123➖
// After: 123➖123456 456
```

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

### `Bun.serve()` reliability improvements

We have made several reliability improvements to `Bun.serve()`. This includes:

- No longer creating unnecessary `DOMException` objects when HTTP requests fail or are aborted
- Fixed a bug where throwing an error when consuming a `ReadableStream` via async iterators could cause an uncatchable global error to be thrown
- Unnecessarily abrupt TLS shutdown caused clients to not receive a WebSocket close frame in some cases
- Serving a `Bun.file()` in certain cases would omit the trailing newline from the response body
- A crash that could occur when abruptly stopping a Bun.serve() server while there are still open HTTP requests has been fixed

### WebSocket server publish after close

A bug where calling `.publish()` on a closed `ServerWebSocket` would incorrectly attempt to publish a message instead of returning `0` has been fixed. In rare cases this could cause a crash.

### WebSocket client receives spurious 1006 close code

We fixed a bug in the `WebSocket` client, where it would receive a spurious `1006` close code, even after sending the server a close frame with a different code. This was because Bun was doing a fast-shutdown, which meant that the close frame was sometimes not sent properly.

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

### Missing `Date` header when sending `Bun.file()` as response

We fixed a bug where the `Date` header was not being sent when sending a `File` as a response in `Bun.serve()`. This was because Bun uses the `sendfile()` syscall for sending files, and that code path was not setting the `Date` header.

```js
const server = Bun.serve({
  async fetch(req) {
    const file = Bun.file("hello.txt");
    return new Response(file);
  },
});

const response = await fetch(server.url);
console.log(response.headers.get("Date"));
// Before: undefined
// After: "Wed, 06 Aug 2024 19:46:05 GMT"
```

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

### Cloned `File` would use the wrong filename

There was a bug where cloning a `File` from another file, while defining a new name, would use the wrong name. This has now been fixed.

```js
const original = Bun.file("original.txt");
const clone = new File([original], "clone.txt");

console.log(clone.name);
// Before: "original.txt"
// After: "clone.txt"
```

### `bun upgrade` on Windows with space in home directory

We fixed a bug where `bun upgrade` would fail on Windows if your home directory contained a space.

```powershell
> bun upgrade
Bun v1.1.22 is out! You're on v1.1.21
Expand-Archive : A positional parameter cannot be found that accepts argument 'PC\AppData\Local\Temp\1.1.22'.
At line:1 char:47
+ ... lyContinue';Expand-Archive -Path bun.zip C:\Users\My PC\AppDat ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [Expand-Archive], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Expand-Archive

error: Failed to verify Bun (code: FileNotFound))
```

If you experienced the following error, it has now been fixed, but you will have to run the PowerShell installer once more to receive the fixed build:

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

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

### UDP socket hangs on macOS 13

Bun uses an undocumented `sendmsg_x()` syscall as a fast-path on macOS to send multiple UDP packets at once, similar to the `sendmmsg()` syscall on Linux. Our usage of the API caused issues on macOS 13, which would cause UDP packets to not be sent. This has now been fixed.

## Thank you to 11 contributors!

- [@billywhizz](htts://github.com/billywhizz)
- [@cirospaciari](htts://github.com/cirospaciari)
- [@dariushalipour](htts://github.com/dariushalipour)
- [@dylan-conway](htts://github.com/dylan-conway)
- [@Electroid](htts://github.com/Electroid)
- [@guest271314](htts://github.com/guest271314)
- [@huseeiin](htts://github.com/huseeiin)
- [@Jarred-Sumner](htts://github.com/Jarred-Sumner)
- [@m1212e](htts://github.com/m1212e)
- [@nektro](htts://github.com/nektro)
- [@paperclover](htts://github.com/paperclover)
- [@pythonmcpi](htts://github.com/pythonmcpi)
