Bun v1.0.27

Jarred Sumner ยท February 17, 2024

Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager โ€” all in one.

This release fixes 72 bugs (addressing 192 ๐Ÿ‘ reactions), Bun Shell supports throwing on non-zero exit codes, stream Response bodies using async generators, improves reliability of fetch(), http2 client, Bun.Glob fixes. Fixes a regression with bun --watch on Linux. Improves Node.js compatibility

Previous releases

  • v1.0.26 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
  • 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 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

To install Bun:

curl -fsSL https://bun.sh/install | bash
npm install -g bun
brew tap oven-sh/bun
brew install bun
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun

To upgrade Bun:

bun upgrade

Bun Shell supports throwing on non-zero exit codes

When we released Bun Shell, we made a small API design mistake. In Bash, shell scripts by default continue running even if a command fails. This is often the cause of subtle bugs in shell scripts. For compatibility, Bun Shell also does this -- but that's not what JavaScript developers expect.

This release adds support for throwing on non-zero exit codes

import { $ } from "bun";


await $`cat /not-found`;

It will throw an error like this:

ShellError: Failed with exit code 1
 info: {
  "stderr": "cat: /not-found: No such file or directory\n",
  "exitCode": 1,
  "stdout": ""

There is an issue with not showing a complete stacktrace in this Error and we are investigating how to fix that.

Upcoming breaking change

After lots of feedback, in Bun v1.1 (not this release), Bun Shell will by default throw on non-zero exit codes - making this the default behavior (a breaking change). We mention in the API docs that Bun Shell is an unstable API and this is a good example of why.

More robust escaping in Bun.Shell

In this release, we made the escaping logic more robust in Bun Shell in situations like this:

import { $ } from "bun";
const str = "cookies & creme";
await $`echo "${str}"`;

Previously, this would escape like so:

await $`echo ""cookies & creme ""`;

Which would lead to the following error:

1 | import { $ } from "bun";
2 | const str = "cookies & creme";
3 | await $`echo "${str}"`;
error: expected a command or assignment but got: "Ampersand"
      at BunShell (:117:69)
      at /private/tmp/sh.js:3:7

Now it correctly escapes like so:

await $`echo "cookies & creme"`;

Stream Response bodies using async generators

This release adds support for streaming Response bodies using async generators

  async fetch(req) {
    return new Response(
      // using an async generator* function
      async function* stream() {
        yield "Hello, ";
        yield Buffer.from("world!");

  async fetch(req) {
    return new Response({
      // You can also pass async iterables
      async *[Symbol.asyncIterator]() {
        yield "Hello, ";
        yield Buffer.from("world!");

You can pass an async generator function or an async iterable to the Response constructor. You can yield string or any TypedArray (like Buffer). Passing a string automatically converts it to a UTF-8 string.

Internally, this becomes a ReadableStream. Bun continues to support ReadableStream directly.

Node.js Readable streams in Bun.serve()

Since Node.js Readable implements [Symbol.asyncIterator], you can now also pass a Node.js Readable stream to the Response constructor.

import { Readable } from "stream";
import { serve } from "bun";

  port: 3001,
  fetch(req) {
    const r = new Readable();
    r.push("your text here");
    return new Response(r);

Fixed: Astro v4.4 rendering empty pages

In Astro v4.4, they switched to using an async generator function to render pages. This caused a bug in Bun where it would render empty pages. This has been fixed.

Fixed: ctrl+c in bun --watch on Linux

A regression in Bun v1.0.26 caused bun --watch to not exit when pressing ctrl+c on Linux. This has been fixed. Sorry about this.

Thanks to @gvilums for fixing this.

Fixed: "ShortRead" in fetch()

In Bun v1.0.21, we added Brotli streaming support to fetch() -- but there was a bug in the implementation when consuming streaming chunks of data to JavaScript. It would throw "error: ShortRead" in some cases. This release fixes that bug, thanks to @argosphil.

Fixed: http2 client hangs

A bug where the http2 client would sometimes hang has been fixed. This was most noticeable when using Firebase or Firestore.

Fixed: crash when calling Bun.$ as a function without a template tag

A crash would occur in code like this:

import { $ } from "bun";

await $("i should've used a template tag instead :(");

Now it correctly throws an error.

Thanks to @zackradisic for fixing this

Fixed: bug with Glob matching ** sometimes returning an empty list

A bug where Bun.Glob with ** would sometimes return an empty list has been fixed, thanks to @zackradisic.

Fixed: support _ in HTTP header names

Previously, Bun.serve() considered header names containing underscores to be invalid. This has been fixed, thanks to @uNetworkingAB.

Fixed: symlink entry points reported import.meta.main as false

In Bun, you can find out if the current module is the entry point using import.meta.main. This was not working correctly when the entry point was a symlink. This has been fixed, thanks to @paperdave.

Fixed: async module mocks in bun:test

A bug where using async or promises inside module mocks was not working correctly has been fixed.

This test now passes:

import { mock, test, expect } from "bun:test";

test("mock.module async", async () => {
  mock.module("i-am-async-and-mocked", async () => {
    await 42;
    await Bun.sleep(0);
    return { a: 123 };

  expect((await import("i-am-async-and-mocked")).a).toBe(123);

Fixed: potential crash in node:crypto

A crash in node:crypto that could potentially occur when using KeyObject has been fixed, thanks to @cirospaciari.

Fixed: path.win32 Node.js tests now pass

The implementation of path.win32 has been rewritten and now passes all Node.js tests, thanks to @jdalton.

Fixed: edgecase in tsconfig.json path mapping

A bug where the tsconfig.json path mapping would not work correctly when multiple possible paths could potentially match and one was longer than the other has been fixed, thanks to @james-elicx.

Fixed: potential crash in Bun.$ when removing lots of files

A potential crash has been fixed when using rm -rf with a large number of files. This was most noticeable on Linux when using in-memory filesystems.

Fixed: potential crash in fetch() after a redirect

A bug in our code for handling redirects in fetch() has been fixed, thanks to @cirospaciari.

Fixed: bun test -t 'pattern' where pattern matched at start

A bug where bun test -t 'pattern' would not match tests where the pattern matched at the start of the test name has been fixed, thanks to @argosphil.

Fixed: potential crash in Bun.stdin, Bun.stdout, Bun.stderr

A bug where using Bun.stdin, Bun.stdout, and Bun.stderr could sometimes crash has been fixed, thanks to @argosphil. This was a regression introduced in Bun v1.0.24.

Bundows is soon

Despite all the non-Windows specific fixes in this release -- most of the code changes are to make Bun work better on Windows (and just not mentioned here since it's not released yet).

We will ship Windows once more of the test suite passes on Windows. 85% of tests pass right now. We are working on getting that to 100% as quickly as possible.

Thanks to 27 contributors!