headroomlabs-ai/headroom · error · Error

Headroom OpenCode transport shim loaded without HEADROOM_OPE

Error message

Headroom OpenCode transport shim loaded without HEADROOM_OPENCODE_TRANSPORT_PROXY_URL

What it means

The Headroom OpenCode transport shim (handler.js) is a preload module: on load it reads HEADROOM_OPENCODE_TRANSPORT_PROXY_URL and immediately installs the transport wrappers. If the module is loaded without that environment variable, it throws at import time because it has no proxy target to route traffic to. This almost always means the shim was preloaded manually or in an environment where the variable was not propagated.

Source

Thrown at headroom/providers/opencode/hook-shim/handler.js:386

  }
  globalThis.fetch = state.originalFetch;
  http.request = state.originalHttpRequest;
  http.get = state.originalHttpGet;
  https.request = state.originalHttpsRequest;
  https.get = state.originalHttpsGet;
  http2.connect = state.originalHttp2Connect;
  childProcess.spawn = state.originalChildSpawn;
  childProcess.exec = state.originalChildExec;
  childProcess.execFile = state.originalChildExecFile;
  childProcess.fork = state.originalChildFork;
  syncBuiltinESMExports();
  setState(void 0);
}

// src/hook-shim.ts
var proxyUrl = process.env.HEADROOM_OPENCODE_TRANSPORT_PROXY_URL;
if (!proxyUrl) {
  throw new Error(
    "Headroom OpenCode transport shim loaded without HEADROOM_OPENCODE_TRANSPORT_PROXY_URL"
  );
}
installHeadroomTransport({ proxyUrl });

View on GitHub (pinned to 322425c43b)

Solutions

  1. Don't preload the shim by hand — launch OpenCode through `headroom opencode` (or the documented wrap command), which sets HEADROOM_OPENCODE_TRANSPORT_PROXY_URL before injecting the shim.
  2. If you must preload it yourself, export the variable first: export HEADROOM_OPENCODE_TRANSPORT_PROXY_URL=http://127.0.0.1:<port> before starting node.
  3. Check that child-process spawns inherit the environment (no env scrubbing) when the shim is active.

Example fix

# before
NODE_OPTIONS="--require /path/hook-shim/handler.js" opencode  # throws: shim loaded without URL

# after
export HEADROOM_OPENCODE_TRANSPORT_PROXY_URL="http://127.0.0.1:8317"
NODE_OPTIONS="--require /path/hook-shim/handler.js" opencode
Defensive patterns

Strategy: validation

Validate before calling

// Run before any process that preloads the shim:
if (process.env.NODE_OPTIONS?.includes("hook-shim") && !process.env.HEADROOM_OPENCODE_TRANSPORT_PROXY_URL) {
  throw new Error("Set HEADROOM_OPENCODE_TRANSPORT_PROXY_URL before preloading the Headroom shim");
}

Try / catch

try {
  require("./hook-shim/handler.js");
} catch (err) {
  if (err instanceof Error && err.message.includes("HEADROOM_OPENCODE_TRANSPORT_PROXY_URL")) {
    process.env.HEADROOM_OPENCODE_TRANSPORT_PROXY_URL = `http://127.0.0.1:${PROXY_PORT}`;
    require("./hook-shim/handler.js"); // retry with env set
  } else throw err;
}

Prevention

When it happens

Trigger: The shim is loaded via NODE_OPTIONS='--require .../hook-shim/handler.js' (or an ESM import hook) in a process whose environment lacks HEADROOM_OPENCODE_TRANSPORT_PROXY_URL — e.g. spawning node from a shell/systemd/cron context that strips env, or manually requiring the shim in tests.

Common situations: Manually adding the shim to NODE_OPTIONS to 'test' it; a child process spawned with a sanitized env (env: {...cleanEnv}); running under sudo or a service manager that drops the variable; a test file importing the hook-shim bundle directly.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/0807dacc9ea89c25. Report an issue: GitHub.