can1357/oh-my-pi · error
blob daemon ${input} responded ${response.status}
Error message
blob daemon ${input} responded ${response.status} What it means
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.
Source
Thrown at packages/coding-agent/src/blob-broker/daemon.ts:63
const ENSURE_ATTEMPTS = 3;
type DaemonInfo = BlobBrokerInfo & { configKey: string };
/** Session-side callback registry the daemon renders lazy blobs through. */
export interface RenderCallbackHost {
/** Start (once) and describe the loopback callback server. */
ensure(): Promise<{ port: number; token: string } | null>;
/** Register the fetcher answering callbacks for `key`. */
register(key: string, fetcher: LazyBlobFetcher): void;
}
async function fetchUnix<T>(socket: string, input: string, init?: RequestInit & { timeoutMs?: number }): Promise<T> {
const response = await fetch(`http://blob-broker.local${input}`, {
...init,
unix: socket,
signal: AbortSignal.timeout(init?.timeoutMs ?? REQUEST_TIMEOUT_MS),
});
if (!response.ok) throw new Error(`blob daemon ${input} responded ${response.status}`);
return (await response.json()) as T;
}
async function probeDaemon(socket: string): Promise<DaemonInfo | null> {
try {
return await fetchUnix<DaemonInfo>(socket, "/info", { timeoutMs: PROBE_TIMEOUT_MS });
} catch {
return null;
}
}
async function liveBlobBrokerSocket(projectDir: string): Promise<string | null> {
if (process.platform === "win32") return null;
try {
const client = await daemonClientForProject(projectDir);
await client.request({ op: "ping" });
const socket = blobBrokerEndpoint(daemonRuntimeDir(client.projectDir));
return (await probeDaemon(socket)) ? socket : null;View on GitHub (pinned to 9690622007)
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.
Example fix
// before
const status = await queryBlobBrokerStatus(projectDir); // throws on 500
// after
let status = null;
try {
status = await queryBlobBrokerStatus(projectDir);
} catch (err) {
logger.warn("blob daemon query failed; falling back to in-process backend", { err });
} Defensive patterns
Strategy: try-catch
Try / catch
try {
const status = await queryBlobBrokerStatus(projectDir);
} catch (err) {
logger.debug("blob daemon request failed; using in-process backend", {
err: err instanceof Error ? err.message : String(err),
});
// fall back to LocalBlobBackend or inline base64
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- bridge call {name!r}: non-JSON response: {body[:200]!r}
- bridge call {name!r} failed
- Daemon broker authentication failed
- Daemon ${operation.name} is ${record.snapshot.state}
- Daemon broker environment is incomplete
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/5e767f2e95d2aa9c.
Report an issue: GitHub.