Skip to content

Compiled binary: Playwright readiness check always fails (import('playwright') can't resolve in single-file bun --compile build) #17

Description

@RichardBray

Bug

Running any command via the installed compiled binary (~/.local/bin/x-dl, built with bun build --compile) always reports Playwright/Chromium as not ready, even when Chromium is correctly installed and launchable.

Repro

$ bunx playwright install chromium   # succeeds, browser downloads fine
$ x-dl install
🔍 Installing Playwright Chromium...
❌ Install failed: Playwright Chromium installation failed or browser is not launchable.

$ x-dl --url-only <tweet-url>
🔍 Checking for Playwright (Chromium)...
❌ Playwright Chromium is not ready

Meanwhile, launching Chromium manually via a plain bun script with node_modules/playwright present works fine (chromium.launch() succeeds, browser opens/closes normally).

Root cause (likely)

isPlaywrightChromiumReady() in src/installer.ts does:

const { chromium } = await import('playwright');
const browser = await chromium.launch({ headless: true });

When x-dl runs as a single-file compiled binary (bun build --compile), there's no node_modules/playwright directory on disk next to the executable. Playwright's launch logic needs its own package folder on disk (to locate the browser registry / driver scripts, not just the bundled JS), so the dynamic import/launch fails inside the compiled binary regardless of whether Chromium is actually installed and cached at ~/Library/Caches/ms-playwright.

This means x-dl install and the pre-flight check in normal usage are effectively broken for every user of the released compiled binaries (from install.sh / GitHub releases), since isPlaywrightChromiumReady() can never return true from that build target.

Workaround

Running from source instead of the compiled binary works, since a real node_modules/playwright exists to resolve against:

git clone https://github.com/RichardBray/x-dl.git
cd x-dl
bun install
bun run src/index.ts <url>

Suggested fix

Playwright's browser-launch and driver-resolution logic assumes a real package directory on disk. Options:

  • Don't bundle Playwright into the compiled binary; instead shell out to a locally-resolved Playwright (e.g. via bunx playwright subprocess) for both the readiness check and the actual extraction, rather than importing it in-process.
  • Or ship the compiled binary alongside a real node_modules/playwright directory (defeats the point of a single-file binary).
  • Or detect process.execPath/compiled-binary context and route Chromium launch through a subprocess wrapper that isn't compiled into the binary.

Confirmed on macOS arm64, x-dl v0.5.0, installed via the official install.sh one-liner.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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