---
title: Bun v1.1.9
description: "Fixes 67 bugs (addressing 150 👍). Fixes to: workspaces in `bun install`, sourcemaps in bun build, IPv6 & VPN connectivity, Loading UNC paths, junctions, symlinks, and pnpm on Windows, `fetch()` gets faster, added `dns.prefetch()` API, `atob()` gets 8x faster, `toString('base64url')` gets 5x faster, expect().toBeReturned() matcher, Node.js compatibility improvements, Bun Shell fixes, and lots more bugfixes."
date: "2024-05-22T00:40:48.496Z"
author: ashcon
draft: false
---

Bun v1.1.9 is here! This release fixes 67 bugs (addressing 150 👍), and includes fixes to workspaces in `bun install`, sourcemaps in `bun build`, IPv6 & VPN connectivity issues, loading UNC paths, junctions, symlinks, and pnpm on Windows. `fetch()` gets faster. A new `dns.prefetch()` API is introduced. `atob()` gets 8x faster. `buffer.toString('base64url')` gets 5x faster. `expect().toBeReturned()` matcher is introduced. We've also made Node.js compatibility improvements and added Bun Shell fixes. Oh, and lots more bugfixes.

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

#### Previous releases

- [`v1.1.8`](/blog/bun-v1.1.8) fixes 54 bugs (addressing 184 👍). Support for `process.on("uncaughtException")` and `process.on("unhandledRejection")`, `JSON.parse` gets faster, Brotli support in `node:zlib`, `[Symbol.dispose]` in Bun APIs, fixes lots of crashes on Windows, and many other bugfixes.
- [`v1.1.7`](/blog/bun-v1.1.7) fixes 28 bugs (addressing 11 👍). Glob workspace names in bun install. Asymmetric matcher support in expect.extends() equals. bunx --version. Bugfixes to JSX transpilation, sourcemaps, cross-compilation of standalone executables, bun shell, RegExp, Worker on Windows, and Node.js compatibility improvements.
- [`v1.1.0`](/blog/bun-v1.1) Bundows. Windows support is here!

#### 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
```

## Workspace fixes

This release includes several fixes to workspaces in `bun install`.

If you run into any more issues with workspaces, please [open an issue](https://bun.sh/issues) and we'll investigate it!

### Fixed: `Workspace dependency "..." not found`

We fixed a bug where running `bun add` to the workspace root, it would fail to add the dependency.

{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">In the next version of Bun<br><br>Several bugs in workspaces are fixed <a href="https://t.co/uxAhJFi0nx">pic.twitter.com/uxAhJFi0nx</a></p>&mdash; Bun (@bunjavascript) <a href="https://twitter.com/bunjavascript/status/1792789280114549208?ref_src=twsrc%5Etfw">May 21, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
{% /raw %}

#### Fixed: `Script not found "..."`

We fixed a bug when running `bun run` in the script of a workspace would not resolve other scripts properly.

```json#package.json
{
  "name": "monorepo",
  "workspaces": ["foo"]
}
```

```json#foo/package.json
{
  "name": "foo",
  "scripts": {
    "prepare": "bun run start",
    "start": "echo 'Starting...'"
  }
}
```

Previously, `bun add` would fail with:

```sh
$ bun add bar
bun add
  ⚙️ bar [1/1] error: Script not found "start"

error: prepare script from "start" exited with 1
```

Now, `bun add` will work as expected:

```sh
$ bun add bar
bun add
  ⚙️ bar [1/1] success
```

### Fixed: Incorrect number of `Removed` packages reported

A bug in the lockfile caused Bun to report an incorrect and sometimes inconsistent number of packages removed when running `bun install/add/remove`.

### Fixed: Crash when non-existent `--cwd` is given to `bun install`

A bug where `bun install --cwd=i-dont-exist` would crash with an unhelpful error message has been fixed.

Big thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing these issues!

### Fixed: Crash with different versions of `bun install`

We fixed a crash when it was possible to run `bun install` using a newer version of Bun, then running `bun add` with an older version of Bun.

```sh
# Run `bun install` using a newer version of Bun
$ bun upgrade --canary
$ bun install

# Run `bun add` with an older version of Bun
$ bun upgrade --stable
$ bun add lodash
```

This has now been fixed thanks to [@dylan-conway](https://github.com/dylan-conway).

## Improved IPv4, IPv6, & VPN connectivity

A longstanding issue where Bun would fail to connect due to the server only broadcasting on either IPv4 or IPv6 has been fixed.

When your computer is connected to a dual-stack network, it is possible for DNS queries to return both IPv4 and IPv6 addresses. This often happened when using a VPN or connecting to `localhost`.

Previously, Bun would not handle this case and would fail to connect to the socket.

For the following input code:

```ts
using server = Bun.serve({
  hostname: "127.0.0.1",
  port: 0,
  fetch() { return new Response("👀😊👀"); }
});

const response = await fetch("http://localhost:" + server.port);
console.log(await response.text());
```

Bun now outputs:

```sh
❯ bun happy-eyeballs.js # New
👀😊👀
```

Previously, Bun would output:

```sh
❯ bun-1.1.8 happy-eyeballs.js # Old
ConnectionRefused: Unable to connect. Is the computer able to access the url?
 path: "http://localhost:64836/"

Bun v1.1.8 (macOS arm64)
```

Now, Bun implements a subset of the IETF standard ["Happy Eyeballs"](https://datatracker.ietf.org/doc/html/rfc6555) algorithm. If Bun receives multiple IP addresses for a single hostname, it will attempt to simultaneously connect to each address, then select the first successful connection.

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

### `fetch()` gets faster DNS resolution

Bun now supports asynchronous DNS resolution in `fetch()` requests.

This means that `fetch()` is faster in scenarios where your operating system does not use a DNS cache, or if you are sending requests to lots of different subdomains. Bun caches these DNS records in-memory, so that they are not re-resolved every time you make a `fetch()` request.

{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">yOu cAnT mAkE fEtCh fAsTeR <a href="https://t.co/Ie8a6YM8Js">pic.twitter.com/Ie8a6YM8Js</a></p>&mdash; Bun (@bunjavascript) <a href="https://twitter.com/bunjavascript/status/1791678083449393219?ref_src=twsrc%5Etfw">May 18, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
{% /raw %}

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

## Asynchronous DNS & Caching

Bun now automatically caches up to 255 DNS records in-memory for a maximum of 30 seconds. This reduces latency when making multiple requests to the same domain over a short period of time.

This applies to:

- `fetch()` requests
- `node:http` requests
- `node:https` requests
- `Bun.connect` requests
- `node:net` requests
- `node:tls` requests

This cache applies to both in-flight DNS requests and completed DNS requests. This means that if you make 50 `fetch()` requests to `example.com` at the same time, it will only resolve the DNS record once. If you wait 31 seconds and make another request, it will ask the operating system for the DNS record again.

This is useful for Docker Containers and environments where the operating system may not have an effective DNS cache.

### New: `dns.prefetch()` API

You can also use the new `dns.prefetch()` API to prefetch DNS records before they are needed. This is useful if you want to pre-warm the DNS cache on startup.

```js
import { dns } from "bun";

// ...on startup
dns.prefetch("example.com");

// ...later on
await fetch("https://example.com/");
```

This will prefetch the DNS record for `example.com` and make it available for use in `fetch()` requests.

### New: `dns.getCacheStats()` API

To observe the DNS cache, you can use the new `dns.getCacheStats()` API.

```js
import { dns } from "bun";

console.log(dns.getCacheStats());
//
// {
//   cacheHitsCompleted: 0,
//   cacheHitsInflight: 0,
//   cacheMisses: 0,
//   size: 0,
//   errors: 0,
//   totalCount: 0,
// }
//

await fetch("https://example.com/");

console.log(dns.getCacheStats());
// {
//   cacheHitsCompleted: 0,
//   cacheHitsInflight: 0,
//   cacheMisses: 1,
//   size: 1,
//   errors: 0,
//   totalCount: 1,
// }
```

### `atob()` gets 8x faster

Thanks to [@lemire](https://github.com/lemire)'s [simdutf](https://github.com/lemire/simdutf) library, `atob()` is now 8x faster in Bun.

{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">In the next version of Bun<br><br>atob() gets 8x faster, thanks to <a href="https://twitter.com/lemire?ref_src=twsrc%5Etfw">@lemire</a>&#39;s simdutf library <a href="https://t.co/5iL1zrZS5d">pic.twitter.com/5iL1zrZS5d</a></p>&mdash; Bun (@bunjavascript) <a href="https://twitter.com/bunjavascript/status/1790658507479646469?ref_src=twsrc%5Etfw">May 15, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
{% /raw %}

### New: Added `bytes()` API to Web streams

Bun now supports the `bytes()` property on Web streams, which returns a `Uint8Array` of the stream's data. This is available on `Request`, `Response`, `Blob`, and `Bun.file()` objects.

```js
const response = await fetch("https://example.com/");
const bytes = await response.bytes();
console.log(bytes); // Uint8Array(1256) [ 60, 33, ... ]
```

`bytes()` is a recent addition to the `fetch()` standard.

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

### New: `bun --no-clear-screen --watch`

You can now use `bun --no-clear-screen` to disable the clearing of the screen when Bun is running in `--watch` or `--hot` mode. This is useful if you want to keep the terminal history after a file reloads.
{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">In the next version of Bun<br><br>The &quot;--no-clear-screen&quot; flag disables clearing the terminal on --watch or --hot<br><br>left: --hot --no-clear-screen<br>right: --hot <a href="https://t.co/TDsTcGx7hh">pic.twitter.com/TDsTcGx7hh</a></p>&mdash; Jarred Sumner (@jarredsumner) <a href="https://twitter.com/jarredsumner/status/1790559318452093009?ref_src=twsrc%5Etfw">May 15, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
{% /raw %}

You can also configure this using the `BUN_CONFIG_NO_CLEAR_TERMINAL_ON_RELOAD` environment variable.

```sh
$ BUN_CONFIG_NO_CLEAR_TERMINAL_ON_RELOAD=1 bun --watch src/index.ts
```

### New: `expect().toHaveReturned()` matchers

Bun now supports the `expect().toHaveReturned()` and `expect().toHaveReturnedTimes(n)` matchers, which are implemented by Jest.

```js
import { expect } from "bun:test";

test("expect().toHaveReturned()", () => {
  const fn = jest.fn(() => "foo");
  fn();
  expect(fn).toHaveReturned();
  fn();
  expect(fn).toHaveReturnedTimes(2);
});
```

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

## Sourcemap improvements

### Bun now loads sourcemaps after `bun build --target=bun --sourcemap`

When you build for production with `bun build --target=bun --sourcemap`, Bun will now load sourcemaps at runtime & use them to map stack traces to the original source code.

```ts
❯ bun out/sourca.js
1 | function mySource(hello: string) {
2 |   throw new Error("woopsie!!");
            ^
error: woopsie!!
      at mySource (/Users/jarred/Desktop/sourca.ts:2:9)
      at /Users/jarred/Desktop/sourca.ts:5:1

Bun v1.1.9 (macOS arm64)
```

Previously:

```ts
❯ bun-1.1.8 out/sourca.js
1 | // @bun
2 | // sourca.ts
3 | var mySource = function(hello) {
4 |   throw new Error("woopsie!!");
            ^
error: woopsie!!
      at mySource (/Users/jarred/Desktop/out/sourca.js:4:9)
      at /Users/jarred/Desktop/out/sourca.js:6:1

Bun v1.1.8 (macOS arm64)
```

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

### Fixed: Sourcemaps off-by-24-bytes error

At runtime, Bun reserves the first 24 bytes of the internal source map buffer for metadata about the sourcemap.

This behavior was only meant to occur at runtime, but it was mistakenly enabled in `bun build` too. This caused sourcemaps to be off by 24 bytes when using `bun build --target=bun --sourcemap`.

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

## Bundows improvements

### Fixed: "Unexpected" reading junctions & symlinks in Windows

In the module resolver code, Bun thought that junctions and symlinks were regular files instead of directories. This caused issues when using monorepos on Windows or when using the `pnpm` package manager with Bun.

The following code now works as expected on Windows:

```ts
import { version } from "lodash";
console.log(version); // 4.17.21
```

Previously:

```ts
error: Unexpected reading 'C:\\abcd\\node_modules\\lodash'
```

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

### Fixed: Loading UNC paths in Windows

When a UNC path was used in various parts of Bun such as `require("\\wsl.local\\path")`, it would fail with an assertion failure about storing posix paths in Windows. This assertion failure was an internal error in Bun, and has now been fixed.

This bug impacted:

- `bun install`
- `bun run <file.ts>`
- `bun <file.ts>`

And more.

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

## Node.js compatiblity improvements

### Fixed: `msw` seems to work now

We fixed a bug in `node:http` where the `statusCode` property was read-only, which could cause an error when trying to set the status code. This was done by packages, such as `msw`, which now work in Bun.

```js
import axios from "axios";
import { http, HttpResponse } from "msw";
import { setupServer } from "msw/node";

const server = setupServer(
  ...[
    http.get("https://example.com/", () => {
      return HttpResponse.json({ msw: "works!" });
    }),
  ],
);
server.listen();
const response = await axios.get("https://example.com/");
console.log(response.data.msw); // "works!"
```

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

### New: Added `shake128` and `shake256` algorithms to `node:crypto`

Bun now supports the `shake128` and `shake256` algorithms in `node:crypto`.

```js
import { createHash } from "node:crypto";

const hash = createHash("shake256");
hash.update("hello");
console.log(hash.digest());
```

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

### `buffer.toString("base64url")` gets 5x faster

Again, thanks to the [simdutf](https://github.com/lemire/simdutf) library, `toString("base64url")` is now 5x faster in Bun.

{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">The fast JavaScript runtime Bun is going to get 5x faster base64 encoding (`toString(&quot;base64url&quot;)`).<a href="https://t.co/BO4PDSOgkS">https://t.co/BO4PDSOgkS</a><br><br>work by <a href="https://twitter.com/jarredsumner?ref_src=twsrc%5Etfw">@jarredsumner</a> <br><br>Relies on the simdutf library <a href="https://t.co/8L5xwdvzKs">https://t.co/8L5xwdvzKs</a><br><br>Node.js already relies on simdutf for these tasks.</p>&mdash; Daniel Lemire (@lemire) <a href="https://twitter.com/lemire/status/1790773632429383966?ref_src=twsrc%5Etfw">May 15, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
{% /raw %}

### Fixed: `http.Agent` not working without `new`

We fixed a bug where you could not construct an `http.Agent` without using the `new` keyword. Some older Node.js APIs, such as `http.Agent` existed before JavaScript introduced classes, and so they did not require the `new` keyword.

```js
import { Agent } from "node:http";

const agent = Agent();
```

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

### Fixed: `newListener` event is emitted in correct order

We fixed an issue where the `newListener` event was being emitted in the wrong order, which could cause issues with some libraries. Previously, the `newListener` event was emitted _after_ the listener was added, but now it is emitted _before_ the listener is added.

```js
import { expect, mock } from "bun:test";
import { Stream } from "node:stream";

test("newListener event is emitted in correct order", () => {
  const stream = new Stream();
  const cb = mock((event) => {
    expect(stream.listenerCount(event)).toBe(0);
  });
  stream.on("newListener", cb);
  stream.on("foo", () => {});
  expect(cb).toHaveBeenCalled();
});
```

### Fixed: Improved argument parsing in `net.connect()`

We fixed various bugs where the argument parsing in `net.connect()` would not match the behavior of Node.js. For example, when a `port` and `host` are provided, or only an `options` object is provided, the `port` and `host` arguments would be ignored.

```js
import { connect } from "node:net";

const socket = connect({
  port: 443,
  host: "localhost",
  rejectUnauthorized: false,
});

socket.on("secureConnect", () => {
  console.log("Connected!");
  socket.end();
});
```

### Fixed: Promisified `child_process.execFile()` returned wrong value

We fixed a bug where the `execFile()` function was not returning the correct value when using the `util.promisify()` function.

```js
import { execFile } from "node:child_process";
import util from "node:util";

const execFileAsync = util.promisify(execFile);
const result = await execFileAsync("ls");

console.log(result);
// Before: 'src\n'
// After: { stdout: 'src\n', stderr: '' }
```

### Fixed: Crash using `which` with long path

We fixed a bug where `Bun.which()` would crash when given a long path. Instead of crashing, it now throws an error: `bin path is too long`.

```js
import { which } from "bun";

which("a".repeat(100000));
// Before: <crash>
// After: <error: bin path is too long>
```

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

### Fixed: Alias `debuglog` to `debug`

We fixed a bug where `util.debuglog()` was not being aliased to `util.debug()`. Thanks to [@gaurishhs](https://github.com/gaurishhs) for fixing this issue.

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

debuglog("foo");
```

### Fixed: `fs.Dirent` now has `path` & `parentPath` properties

We fixed a bug where the `path` property and the new `parentPath` properties were not being set on `fs.Dirent` objects. This could cause issues when using `fs.Dirent` objects in conjunction with `fs.readdir()`.

```js
import { readdirSync } from "node:fs";

readdirSync("src").forEach((dirent) => {
  console.log(dirent.path);
  // Before: undefined
  // After: 'src'
});
```

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

### Fixed: `must be a number or a Date`

We fixed a bug where certain APIs that interpret arguments as double would throw an error due to incorrect integer coercion.

```js
import { utimesSync } from "node:fs";

const atime = Math.floor(Date.now() / 1000);
const mtime = Math.floor(Date.now() / 1000);
utimesSync("hello.txt", atime, mtime);

// Before: Error: Argument must be a number or a Date
// After: <no error>
```

This has now been fixed thanks to [@dylan-conway](https://github.com/dylan-conway).

## Bun Shell improvements

### Escaping more characters

We fixed bugs where special characters, such as `|`, `&`, and `;`, that need to be escaped when used in a shell, but were not being escaped.

```sh
$ bun shell 'echo "Hello, world!" | grep "world"'
# Hello, world!

$ bun shell 'echo "Hello, world!" | grep "world"'
# Hello, world!
```

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

### Tilde expansion in Bun shell

The [Bun shell](/docs/runtime/shell) now supports tilde expansion, which means you can use `~` (aka. tilde) to refer to your home directory. For example, `~/Documents` will expand to the path of `$HOME/Documents`.

This is supported on all platforms, including Windows.

```sh
echo ~
# /Users/bun

echo ~/Documents
# /Users/bun/Documents
```

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

### Fixed: `cd` would return the wrong exit code

We fixed a bug where `cd` would return the wrong exit code run in the Bun shell. This would happen when there was an error changing directories.

```sh
$ cd /not/a/directory
$ echo $?
0
```

### Fixed: Crash when pasting very large input in argv0

A bug where pasting too large input into the first argument of the Bun shell would crash has been fixed.

```sh
$ bun exec ${"a".repeat(100_000_000)}
```

The bug was caused by a missing bounds check in `which`. Operating systems have a maximum length of 512, 1024, or 4096 bytes for file paths and when that limit is exceeded Bun would crash.

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

## Thanks to 16 contributors!

- [@ahaoboy](https://github.com/ahaoboy)
- [@ananis25](https://github.com/ananis25)
- [@DaleSeo](https://github.com/DaleSeo)
- [@dylan-conway](https://github.com/dylan-conway)
- [@gaurishhs](https://github.com/gaurishhs)
- [@gvilums](https://github.com/gvilums)
- [@jakeboone02](https://github.com/jakeboone02)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@lafkpages](https://github.com/lafkpages)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@ridiculousfish](https://github.com/ridiculousfish)
- [@SunsetTechuila](https://github.com/SunsetTechuila)
- [@vitch](https://github.com/vitch)
- [@zackradisic](https://github.com/zackradisic)
