{"record":{"id":"0807dacc9ea89c25","repo":"headroomlabs-ai/headroom","slug":"headroom-opencode-transport-shim-loaded-without-he","errorCode":null,"errorMessage":"Headroom OpenCode transport shim loaded without HEADROOM_OPENCODE_TRANSPORT_PROXY_URL","messagePattern":"Headroom OpenCode transport shim loaded without HEADROOM_OPENCODE_TRANSPORT_PROXY_URL","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"headroom/providers/opencode/hook-shim/handler.js","lineNumber":386,"sourceCode":"  }\n  globalThis.fetch = state.originalFetch;\n  http.request = state.originalHttpRequest;\n  http.get = state.originalHttpGet;\n  https.request = state.originalHttpsRequest;\n  https.get = state.originalHttpsGet;\n  http2.connect = state.originalHttp2Connect;\n  childProcess.spawn = state.originalChildSpawn;\n  childProcess.exec = state.originalChildExec;\n  childProcess.execFile = state.originalChildExecFile;\n  childProcess.fork = state.originalChildFork;\n  syncBuiltinESMExports();\n  setState(void 0);\n}\n\n// src/hook-shim.ts\nvar proxyUrl = process.env.HEADROOM_OPENCODE_TRANSPORT_PROXY_URL;\nif (!proxyUrl) {\n  throw new Error(\n    \"Headroom OpenCode transport shim loaded without HEADROOM_OPENCODE_TRANSPORT_PROXY_URL\"\n  );\n}\ninstallHeadroomTransport({ proxyUrl });\n","sourceCodeStart":368,"sourceCodeEnd":391,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/providers/opencode/hook-shim/handler.js#L368-L391","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nNODE_OPTIONS=\"--require /path/hook-shim/handler.js\" opencode  # throws: shim loaded without URL\n\n# after\nexport HEADROOM_OPENCODE_TRANSPORT_PROXY_URL=\"http://127.0.0.1:8317\"\nNODE_OPTIONS=\"--require /path/hook-shim/handler.js\" opencode","handlingStrategy":"validation","validationCode":"// Run before any process that preloads the shim:\nif (process.env.NODE_OPTIONS?.includes(\"hook-shim\") && !process.env.HEADROOM_OPENCODE_TRANSPORT_PROXY_URL) {\n  throw new Error(\"Set HEADROOM_OPENCODE_TRANSPORT_PROXY_URL before preloading the Headroom shim\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  require(\"./hook-shim/handler.js\");\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"HEADROOM_OPENCODE_TRANSPORT_PROXY_URL\")) {\n    process.env.HEADROOM_OPENCODE_TRANSPORT_PROXY_URL = `http://127.0.0.1:${PROXY_PORT}`;\n    require(\"./hook-shim/handler.js\"); // retry with env set\n  } else throw err;\n}","preventionTips":["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)."],"tags":["environment","configuration","nodejs","opencode","proxy"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}