garrytan/gstack · error · BrowseClientError

127

127

Error message

browse resolve exited 127: browse binary not found.

make-pdf needs browse (the gstack Chromium daemon) to render PDFs.
Tried:
  - $GSTACK_BROWSE_BIN (${env.GSTACK_BROWSE_BIN || "unset"})
  - $BROWSE_BIN (${env.BROWSE_BIN || "unset"})
  - sibling: ${siblingCandidates.join(", ")}
  - global: ${globalPath}
  - PATH: `browse`

To fix: run gstack setup from the gstack repo:
  cd ~/.claude/skills/gstack && ./setup

Or set GSTACK_BROWSE_BIN explicitly:
  ${GSTACK_BROWSE_BIN export/setx line}

What it means

BrowseClientError with exitCode 127 thrown by resolveBrowseBin() when the browse binary cannot be located in any of five resolution tiers: GSTACK_BROWSE_BIN/BROWSE_BIN env overrides, sibling dist paths, the global ~/.claude/skills/gstack install, or PATH. make-pdf needs browse (the gstack Chromium daemon) to render PDFs. The message is a canonical setup recipe, not just a path.

Source

Thrown at make-pdf/src/browseClient.ts:134

  ];
  for (const candidate of siblingCandidates) {
    const found = findExecutable(candidate);
    if (found) return found;
  }

  // 4: global install.
  const home = os.homedir();
  const globalPath = path.join(home, ".claude/skills/gstack/browse/dist/browse");
  const globalFound = findExecutable(globalPath);
  if (globalFound) return globalFound;

  // 5: PATH lookup via Bun.which — handles Windows PATHEXT natively (no `which`
  // dependency on cmd.exe / PowerShell, no `where`-vs-`which` branch).
  const PATH = env.PATH ?? env.Path ?? '';
  const onPath = Bun.which('browse', { PATH });
  if (onPath) return onPath;

  throw new BrowseClientError(
    /* exitCode */ 127,
    "resolve",
    [
      "browse binary not found.",
      "",
      "make-pdf needs browse (the gstack Chromium daemon) to render PDFs.",
      "Tried:",
      `  - $GSTACK_BROWSE_BIN (${env.GSTACK_BROWSE_BIN || "unset"})`,
      `  - $BROWSE_BIN (${env.BROWSE_BIN || "unset"})`,
      `  - sibling: ${siblingCandidates.join(", ")}`,
      `  - global: ${globalPath}`,
      "  - PATH: `browse`",
      "",
      "To fix: run gstack setup from the gstack repo:",
      "  cd ~/.claude/skills/gstack && ./setup",
      "",
      "Or set GSTACK_BROWSE_BIN explicitly:",
      process.platform === "win32"

View on GitHub (pinned to 94993f7401)

Solutions

  1. Run `cd ~/.claude/skills/gstack && ./setup` to (re)build and install browse.
  2. Set GSTACK_BROWSE_BIN to an absolute path of an existing browse binary (`export GSTACK_BROWSE_BIN=/path/to/browse`).
  3. Confirm the binary is executable: `chmod +x <browse>` (POSIX) or unblock it (Windows).
  4. Run `bun run build` in the gstack repo to produce browse/dist/browse, then retry.

Example fix

# before
$ pdf report.md
Error: browse resolve exited 127: browse binary not found. ...

# after — install browse, then render
$ cd ~/.claude/skills/gstack && ./setup
$ export GSTACK_BROWSE_BIN="$HOME/.claude/skills/gstack/browse/dist/browse"
$ pdf report.md
Defensive patterns

Strategy: validation

Validate before calling

import { resolveBrowseBin, BrowseClientError } from './browseClient';
import fs from 'node:fs';

function ensureBrowseAvailable(env = process.env): void {
  try {
    const bin = resolveBrowseBin(env);
    if (!fs.existsSync(bin)) throw new Error(`resolved browse binary missing: ${bin}`);
  } catch (e) {
    if (e instanceof BrowseClientError && e.exitCode === 127) {
      throw new Error('Run `cd ~/.claude/skills/gstack && ./setup` before rendering PDFs.');
    }
    throw e;
  }
}

ensureBrowseAvailable();

Type guard

import { BrowseClientError } from './browseClient';
function isBrowseMissing(e: unknown): e is BrowseClientError {
  return e instanceof BrowseClientError && e.exitCode === 127;
}

Try / catch

try {
  await generate(opts);
} catch (e) {
  if (isBrowseMissing(e)) {
    console.error('browse not installed — run ./setup from the gstack repo, then retry.');
    process.exit(127);
  }
  throw e;
}

Prevention

When it happens

Trigger: First make-pdf run on a machine where gstack ./setup was never run; GSTACK_BROWSE_BIN points to a deleted/moved binary; a compiled pdf binary invoked from a directory whose sibling/browse layout differs from the expected dist/ layout; PATH lacks the browse install dir; the global install was partially deleted.

Common situations: Fresh CI worker without the gstack skill installed; a user who only `bun install`-ed make-pdf without building browse; moving the repo after setting a relative GSTACK_BROWSE_BIN; macOS Gatekeeper quarantine stripping the executable bit; Windows where the .exe extension requires PATHEXT resolution that Bun.which handles but a hand-set env var does not.

Related errors


AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12). Data as JSON: /api/errors/badaff75c1e0ba06. Report an issue: GitHub.