Skip to content

bun build --compile fails on virtiofs mounts (devcontainers) #407

@richardrigby

Description

@richardrigby

Summary

bun build --compile fails inside devcontainers that use virtiofs-mounted filesystems. This breaks the ./setup script — the browse binary at browse/dist/browse is never rebuilt, leaving a stale binary that can't locate server.ts. The result is every $B command hanging with:

[browse] Another instance is starting the server, waiting...
[browse] Timed out waiting for another instance to start the server

Root Cause

Bun's --compile flag writes output to a temp file (e.g. /run/host_virtiofs/.../.bun-build) and then does an atomic rename() to the target path. On virtiofs mounts, this rename fails with ENOENT:

[9ms]  bundle  2 modules
failed to rename /run/host_virtiofs/.../.189f99fd7dcbfffb-00000000.bun-build to browse/dist/browse: ENOENT

The setup script has || true at the end of the build pipeline, so this failure is silently swallowed and setup reports success:

gstack ready (claude).
  browse: /path/to/browse/dist/browse

The stale compiled binary has wrong embedded import.meta.dir and process.execPath values, so resolveServerScript() in cli.ts can't find server.ts. The server process never starts, and acquireServerLock() in ensureServer() times out waiting for a state file that will never appear.

Reproduction

  1. Run VS Code / Cursor with a devcontainer on macOS (Docker Desktop with virtiofs)
  2. Install gstack and run ./setup
  3. Observe bun build --compile failure in output (easy to miss due to || true)
  4. Run any $B command → hangs and times out

Workaround

Replace the compiled binary with a shell wrapper that delegates to bun run:

#!/bin/sh
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
exec bun run "$SCRIPT_DIR/../src/cli.ts" "$@"

This works because bun itself runs fine on virtiofs — only bun build --compile is broken (it's a known Bun issue with cross-mount atomic renames).

Suggested Fix Options

  1. Shell wrapper fallback in setup: After bun build --compile fails, detect the failure and write the shell wrapper automatically. This is the simplest fix and works everywhere.

  2. Build in /tmp and copy: cd /tmp && bun build --compile .../cli.ts --outfile /tmp/browse && cp /tmp/browse .../browse/dist/browse — avoids the virtiofs rename issue since /tmp is a normal filesystem.

  3. Detect virtiofs and skip compile: Check if the working directory is on a virtiofs mount and use the wrapper approach by default.

Option 1 is probably the most robust since it handles any filesystem where bun build --compile fails, not just virtiofs.

Environment

  • Docker Desktop with virtiofs (macOS host → Linux container)
  • Bun 1.3.x
  • The issue is upstream in Bun (oven-sh/bun#4253) but the gstack setup should handle it gracefully

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions