---
title: Bun v1.0.26
description: "Fixes 30 bugs (addressing 60 👍 reactions), adds support for multi-statement queries in bun:sqlite, makes bun --watch more reliable in longer-running sessions, Bun.FileSystemRouter now supports more than 64 routes, fixes a bug with expect().toStrictEqual(), fixes 2 bugs with error.stack,  improves Node.js compatibility"
date: "2024-02-03T16:40:08.202Z"
author: jarred
draft: false
---

Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager &mdash; all in one. In case you missed it, here are some of the recent changes to Bun.

This release fixes 30 bugs, adds support for multi-statement queries in bun:sqlite, makes bun --watch more reliable in longer-running sessions, Bun.FileSystemRouter now supports more than 64 routes, fixes a bug with expect().toStrictEqual(), fixes 2 bugs with error.stack, fixes a bug with fileURLToPath, improves Node.js compatibility

#### Previous releases

- [`v1.0.25`](/blog/bun-v1.0.25) fixes 4 bugs, adds vm.createScript. Fixes a crash in fs.readFile, a crash in Bun.file().text(), a crash in IPC, and a transpiler bug involving loose equals
- [`v1.0.24`](/blog/bun-v1.0.24) fixes 9 bugs and adds Bun Shell, a fast cross-platform shell with seamless JavaScript interop. Fixes a socket timeout bug, a potential crash when socket closes, a Node.js compatibility issue with Hapi, a process.exit bug, and bun install binlinking bug, bun inspect regression, and bun:test expect().toContain bug
- [`v1.0.23`](/blog/bun-v1.0.23) fixes 40 bugs (addressing 194 👍 reactions). import & embed sqlite databases in Bun, Resource Management ('using' TC39 stage3) support, bundler improvements when building for Node.js, bugfix for peer dependency resolution, semver bugfix, 4% faster TCP on linux, Node.js compatibility improvements and more"

To install Bun:

{% codetabs %}

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

```sh#npm
$ npm install -g 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
```

## Multi-statement queries in bun:sqlite

[`bun:sqlite`](https://bun.sh/docs/api/sqlite) gets support for multi-statement queries. This allows you to run multiple SQL statements in a single call to `db.run()` delimited by a `;`, similar to how it works in the `sqlite` command-line tool.

```js
import { Database } from "bun:sqlite";

const db = new Database(":memory:");

db.run(`
  CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name TEXT
  );

  INSERT INTO users (name) VALUES ("Alice");
  INSERT INTO users (name) VALUES ("Bob");
`);

const names = db
  .query("SELECT name FROM users")
  .all()
  .map(({ name }) => name)
  .join(", ");
console.log(names); // Alice, Bob
```

Only `Database.prototype.run` and ``Database.prototype.exec` support multi-statement queries. `db.query` and `db.prepare` do not.

## bun --watch reliability improvement

`bun --watch` now defensively closes all file descriptors on reload. Filesystem watchers inherently need to keep many file descriptors open when watching many files, but keeping file descriptors open for a long time can lead to resource exhaustion and many other issues. Bun already set `O_CLOEXEC` internally, but that doesn't always mean all file descriptors closed.

Part of what makes `bun --watch` fast is we immediately reload the entire process when an imported file changes. There's very little work that happens between the file change and the process reload. This is in contrast to other tools that might recompile the file to check for changes, and only re-run the process on change.

On Linux, Bun now uses the [`close_range(2)`](https://man7.org/linux/man-pages/man2/close_range.2.html) system call to close all file descriptors > 8 before reloading the process. This reliably ensures that all file descriptors are closed (for those of you running modern Linux kernels).

On macOS, we use the `POSIX_SPAWN_CLOEXEC_DEFAULT` flag to close all file descriptors on spawn. We also fixed an issue where signals were not being reset to their default behavior on reload.

## `abort-controller` polyfill now uses native `AbortController`

The popular `abort-controller` npm package polyfill now uses the native `AbortController` in Bun instead of the polyfill.

This fixes an issue where Bun would report an error like `"Expected signal to be an AbortSignal"` when a library used the `abort-controller` polyfill with `fetch` or `Request` or `Response`.

The `abort-controller` polyfill is a polyfill for the `AbortController` and `AbortSignal` web APIs

## Fixed: Bun.FileSystemRouter now supports more than 64 routes

[Bun.FileSystemRouter](https://bun.sh/docs/api/file-system-router) is Bun's built-in Next.js pages-inspired filesystem router. It now supports more than 64 routes.

Previously, Bun would throw an uncatchable exception when you tried to use more than 64 routes. This was caused by an assertion failure in JavascriptCore when an object is defined with more than 63 "inline" properties. This has been fixed.

## Fixed: error.stack sometimes `undefined`

Bun implements the [V8 Stack Trace API](https://v8.dev/docs/stack-trace-api) (despite Bun using the JavaScriptCore engine), which adds methods like `Error.prepareStackTrace` and `Error.captureStackTrace` to the `Error` object.

There was a bug where `error.stack` was sometimes `undefined` when it should have been a string. This has been fixed.

This bug impacted Firebase & Google Cloud libraries when they were about to log an error. It caused these libraries to throw a different error while trying to log the error, which was not helpful.

## Fixed: error.stack CallSite lineNumber was sometimes negative

The following would sometimes print negative numbers:

```js
Error.prepareStackTrace = (error, stack) => {
  return [stack[0].getLineNumber(), stack[0].getColumnNumber()];
};

const error = new Error();
console.log(error.stack);
```

Bun returned negative numbers when the line number was not available. This unfortunately broke the popular `source-map-support` library since it asserts that line and column numbers are positive integers. This has been "fixed" by never returning negative numbers.

## Fixed: `Error.prepareStackTrace` is now a function by default

In Node.js, `Error.prepareStackTrace` is a function by default. In Bun, it was `undefined` by default. This has been fixed.

The default `Error.prepareStackTrace` function does what you would expect: it returns a string of the stack trace. You can continue to set `Error.prepareStackTrace` to a custom function to customize the stack trace, or to `undefined` (in which case the default function is used).

## Fixed: `module.path` is now `__dirname` instead of `module.id`

In Node.js, the `module` object has a `path` property which is supposed to be the directory of the module, equivalent to `__dirname`. In Bun, `module.path` was incorrectly an alias for `module.id`. This has been fixed.

## Fixed: `expect(a).toStrictEqual(b)` with deleted properties

A bug in `bun:test`'s `expect.toStrictEqual` implementation caused it to behave incorrectly when comparing objects with deleted properties. This has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).

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

test("expect.toStrictEqual", () => {
  const a = { a: 1, b: 2 };
  const b = { a: 1, b: 2 };
  delete b.b;
  expect(a).toStrictEqual(b);
});
```

Previously, this would throw an error with a confusingly empty diff:

```js
hey.test.ts:
2 |
3 | test("expect.toStrictEqual", () => {
4 |   var obj1 = { a: 1 };
5 |   var obj2 = {};
6 |   delete obj1.a;
7 |   expect(obj1).toStrictEqual(obj2);
      ^
error: expect(received).toStrictEqual(expected)

  {}

- Expected  - 0
+ Received  + 0

      at hey.test.ts:7:3
✗ expect.toStrictEqual [0.29ms]
```

Now it correctly passes.

This happened because toStrictEqual used a fast path that failed to handle deleted properties correctly in some cases.

## Fixed: event loop scheduling bug in Bun.serve() websockets

We've made some infrastructure tweaks to ensure that microtasks are always drained after event loop callbacks are executed. There was a bug where we skipped doing this in websockets, in Bun.spawn(), and in IPC handlers. Neglecting to drain the microtask queue can cause very high memory growth until the microtasks get drained (imagine if you just kept adding to a queue without ever removing anything).

## Fixed: new Response(Bun.file()) sometimes logged an error to stderr

When you passed a `Bun.file()` to `new Response()` to `Bun.serve()` connected to HTTP (not HTTPS), if the client aborted the request at the right time, Bun would log `Error: NOTCONN` to stderr with no way to suppress it. This was confusing and unhelpful. Aborting a request is a normal part of the web, and Bun should not log an unsupressable error when it happens.

## Windows is happening on February 15th

78% of Bun's tests pass on Windows, but it's still not enough to release.

Most of the changes in this release were Windows-related, but this changelog excludes that since its not "released" yet.

## Thanks to 28 contributors!

- [@fneco](https://github.com/fneco)
- [@jcarpe](https://github.com/jcarpe)
- [@nektro](https://github.com/nektro)
- [@nullun](https://github.com/nullun)
- [@A-D-E-A](https://github.com/A-D-E-A)
- [@blimmer](https://github.com/blimmer)
- [@DaleSeo](https://github.com/DaleSeo)
- [@gvilums](https://github.com/gvilums)
- [@jdalton](https://github.com/jdalton)
- [@moznion](https://github.com/moznion)
- [@Primexz](https://github.com/Primexz)
- [@zack466](https://github.com/zack466)
- [@cyfdecyf](https://github.com/cyfdecyf)
- [@guarner8](https://github.com/guarner8)
- [@huseeiin](https://github.com/huseeiin)
- [@Didas-git](https://github.com/Didas-git)
- [@Electroid](https://github.com/Electroid)
- [@paperclover](https://github.com/paperclover)
- [@FireSquid6](https://github.com/FireSquid6)
- [@TiranexDev](https://github.com/TiranexDev)
- [@vinnichase](https://github.com/vinnichase)
- [@whygee-dev](https://github.com/whygee-dev)
- [@BeyondMagic](https://github.com/BeyondMagic)
- [@eliot-akira](https://github.com/eliot-akira)
- [@lukeingalls](https://github.com/lukeingalls)
- [@cirospaciari](https://github.com/cirospaciari)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
