{"record":{"id":"5e767f2e95d2aa9c","repo":"can1357/oh-my-pi","slug":"blob-daemon-input-responded-response-status","errorCode":null,"errorMessage":"blob daemon ${input} responded ${response.status}","messagePattern":"blob daemon (.+?) responded (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/blob-broker/daemon.ts","lineNumber":63,"sourceCode":"const ENSURE_ATTEMPTS = 3;\n\ntype DaemonInfo = BlobBrokerInfo & { configKey: string };\n\n/** Session-side callback registry the daemon renders lazy blobs through. */\nexport interface RenderCallbackHost {\n\t/** Start (once) and describe the loopback callback server. */\n\tensure(): Promise<{ port: number; token: string } | null>;\n\t/** Register the fetcher answering callbacks for `key`. */\n\tregister(key: string, fetcher: LazyBlobFetcher): void;\n}\n\nasync function fetchUnix<T>(socket: string, input: string, init?: RequestInit & { timeoutMs?: number }): Promise<T> {\n\tconst response = await fetch(`http://blob-broker.local${input}`, {\n\t\t...init,\n\t\tunix: socket,\n\t\tsignal: AbortSignal.timeout(init?.timeoutMs ?? REQUEST_TIMEOUT_MS),\n\t});\n\tif (!response.ok) throw new Error(`blob daemon ${input} responded ${response.status}`);\n\treturn (await response.json()) as T;\n}\n\nasync function probeDaemon(socket: string): Promise<DaemonInfo | null> {\n\ttry {\n\t\treturn await fetchUnix<DaemonInfo>(socket, \"/info\", { timeoutMs: PROBE_TIMEOUT_MS });\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function liveBlobBrokerSocket(projectDir: string): Promise<string | null> {\n\tif (process.platform === \"win32\") return null;\n\ttry {\n\t\tconst client = await daemonClientForProject(projectDir);\n\t\tawait client.request({ op: \"ping\" });\n\t\tconst socket = blobBrokerEndpoint(daemonRuntimeDir(client.projectDir));\n\t\treturn (await probeDaemon(socket)) ? socket : null;","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/blob-broker/daemon.ts#L45-L81","documentation":"fetchUnix performs HTTP requests over the blob daemon's Unix socket and throws this error for any non-2xx response from the daemon's control API (/info, /status, /doctor, /probe, /purge, /blob). The message carries the endpoint path and HTTP status so callers can see which daemon operation failed and how.","triggerScenarios":"Any queryBlobBroker* call or DaemonBlobBackend.ensureBlob/ensureLazy when the daemon responds with an error status — daemon internal failure, malformed request body, or the endpoint returning 404/500.","commonSituations":"Blob daemon crashed mid-request or its exposure died so /probe fails; POSTing to /blob with an oversized payload rejected by the daemon; calling an endpoint the running daemon version does not implement (version skew between client and daemon).","solutions":["Check the daemon's stderr/log for the underlying cause of the non-2xx response.","Restart the blob daemon (stopQuietly or restart the omp daemon) so it comes back with a fresh exposure.","Upgrade omp so client and daemon speak the same protocol version.","Reduce the request size (e.g. smaller image payload) if the daemon rejected a large upload."],"exampleFix":"// before\nconst status = await queryBlobBrokerStatus(projectDir); // throws on 500\n// after\nlet status = null;\ntry {\n  status = await queryBlobBrokerStatus(projectDir);\n} catch (err) {\n  logger.warn(\"blob daemon query failed; falling back to in-process backend\", { err });\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const status = await queryBlobBrokerStatus(projectDir);\n} catch (err) {\n  logger.debug(\"blob daemon request failed; using in-process backend\", {\n    err: err instanceof Error ? err.message : String(err),\n  });\n  // fall back to LocalBlobBackend or inline base64\n}","preventionTips":["The daemon client functions already return null for stopped daemons — keep requests short-lived and tolerate failure.","Restart the daemon when you see repeated 5xx responses; stale daemons after crashes are the usual cause.","Keep omp versions homogeneous across processes sharing the daemon to avoid protocol skew."],"tags":["http","daemon","ipc"],"backgroundTag":"http-5xx-from-daemon","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}