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
- 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.
- 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.
- 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
- Always launch via `headroom opencode` rather than hand-setting NODE_OPTIONS.
- When spawning child processes under the shim, pass process.env through unchanged.
- In tests that import the shim, set the env var in a setup-before-import block (jest setupFiles, vitest setup).
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
- Headroom OpenCode wrap blocked direct HTTP/2 connection to $
- Invalid {TOOL_INJECTION_STICKY_ENV}={normalized!r}; expected
- Headroom OpenCode transport shim loaded without HEADROOM_OPE
- Headroom OpenCode transport shim loaded without HEADROOM_OPE
- {env_var} must be a JSON object of header name/value strings
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/0807dacc9ea89c25.
Report an issue: GitHub.