{"record":{"id":"c62a42f4baba4955","repo":"can1357/oh-my-pi","slug":"blob-broker-worker-requires-blob-broker-socket-e","errorCode":null,"errorMessage":"blob broker worker requires ${BLOB_BROKER_SOCKET_ENV} and ${BLOB_BROKER_CONFIG_ENV}","messagePattern":"blob broker worker requires (.+?) and (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/blob-broker/server.ts","lineNumber":152,"sourceCode":"\t\t\t\t\theaders: { [RENDER_CALLBACK_TOKEN_HEADER]: token },\n\t\t\t\t\tsignal: AbortSignal.timeout(CALLBACK_TIMEOUT_MS),\n\t\t\t\t});\n\t\t\t\tif (!response.ok) return null;\n\t\t\t\treturn new Uint8Array(await response.arrayBuffer());\n\t\t\t});\n\t\t\tif (!publication) return json({ error: \"unavailable\" }, 503);\n\t\t\treturn json({ publication } satisfies EnsureBlobResponse);\n\t\t}\n\t\treturn json({ error: \"not found\" }, 404);\n\t};\n}\n\n/** Boot the blob daemon from worker environment variables and serve forever. */\nexport async function startBlobBrokerFromEnvironment(): Promise<void> {\n\tconst socketPath = Bun.env[BLOB_BROKER_SOCKET_ENV];\n\tconst configJson = Bun.env[BLOB_BROKER_CONFIG_ENV];\n\tif (!socketPath || !configJson) {\n\t\tthrow new Error(`blob broker worker requires ${BLOB_BROKER_SOCKET_ENV} and ${BLOB_BROKER_CONFIG_ENV}`);\n\t}\n\tconst config = JSON.parse(configJson) as BlobBrokerWorkerConfig;\n\tconst backend = new LocalBlobBackend(config);\n\t// Bring the exposure up before advertising readiness so a ready daemon is a\n\t// serving daemon. Uploader configs have nothing to start.\n\tconst baseUrl = isUploaderKind(config.kind) ? \"\" : await backend.ensureStarted();\n\tif (baseUrl === null) {\n\t\tthrow new Error(\"blob broker exposure failed to start\");\n\t}\n\ttry {\n\t\tfs.rmSync(socketPath, { force: true });\n\t} catch {\n\t\t// A live daemon holding the socket loses the start race in the broker.\n\t}\n\tBun.serve({ unix: socketPath, fetch: createControlHandler(backend, config, baseUrl) });\n\t// The daemon broker tears us down with a signal; flush the persisted\n\t// url index rather than losing the debounced write.\n\tprocess.on(\"SIGTERM\", () => {","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/blob-broker/server.ts#L134-L170","documentation":"startBlobBrokerFromEnvironment() boots the blob broker daemon inside a worker, reading its socket path and JSON config from fixed environment variables (BLOB_BROKER_SOCKET_ENV / BLOB_BROKER_CONFIG_ENV). It throws when either variable is missing or empty — i.e. the function was invoked outside the broker worker harness that is supposed to set them.","triggerScenarios":"Calling startBlobBrokerFromEnvironment() directly (or via runWorkerEntrypoint) without first setting both env vars; spawning the worker without passing env; a typo'd or stripped env when constructing the Worker.","commonSituations":"Manual testing of the worker entrypoint in a plain shell; spawning the worker with a custom env object that dropped the broker vars; refactors renaming the env constants so the spawner and the reader disagree.","solutions":["Set both env vars before invoking: BLOB_BROKER_SOCKET_ENV=<socket path> and BLOB_BROKER_CONFIG_ENV=<JSON config>, e.g. via the same Worker spawn options the broker normally uses","Spawn the worker through the existing broker code path instead of invoking the entry function manually","If spawning manually, pass env: { ...process.env, [BLOB_BROKER_SOCKET_ENV]: sock, [BLOB_BROKER_CONFIG_ENV]: JSON.stringify(config) }","Verify the config JSON also parses — this guard runs before JSON.parse, so fix env first, then config contents"],"exampleFix":"// before: worker spawned without its env\nnew Worker(entry, { type: \"module\" });\n// after\nnew Worker(entry, {\n  type: \"module\",\n  env: {\n    ...process.env,\n    [BLOB_BROKER_SOCKET_ENV]: socketPath,\n    [BLOB_BROKER_CONFIG_ENV]: JSON.stringify(config),\n  },\n});","handlingStrategy":"validation","validationCode":"// verify the harness env before booting\nimport { BLOB_BROKER_SOCKET_ENV, BLOB_BROKER_CONFIG_ENV } from \"./env\";\nif (!Bun.env[BLOB_BROKER_SOCKET_ENV] || !Bun.env[BLOB_BROKER_CONFIG_ENV]) {\n  throw new Error(`worker misconfigured: set ${BLOB_BROKER_SOCKET_ENV} and ${BLOB_BROKER_CONFIG_ENV}`);\n}\nJSON.parse(Bun.env[BLOB_BROKER_CONFIG_ENV]); // config must also be valid JSON","typeGuard":null,"tryCatchPattern":"try {\n  await startBlobBrokerFromEnvironment();\n} catch (err) {\n  if (String(err.message).includes(\"blob broker worker requires\")) {\n    logger.error(\"broker worker spawned without required env\", { err });\n  }\n  throw err;\n}","preventionTips":["Always spawn the worker through the existing broker spawn path, not by hand","Pass env: { ...process.env, ...brokerEnv } explicitly in Worker options","If env constant names change, update spawner and reader together in one commit","Smoke-test worker startup in CI with the real env wiring"],"tags":["environment","worker","configuration"],"backgroundTag":"missing-env-var","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}