can1357/oh-my-pi · error
${destination} returned invalid JSON
Error message
${destination} returned invalid JSON What it means
After a successful HTTP status, jsonResponse calls response.json() to decode the body. If the body is not valid JSON (HTML error page, empty body, truncated stream), this error is thrown naming the destination. Note it is thrown only after expectOk passes, so the host returned a success status with a non-JSON body.
Source
Thrown at packages/coding-agent/src/blob-broker/uploaders-image-hosts.ts:42
consumerSecret: string;
token: string;
tokenSecret: string;
}
function responseRecord(value: unknown, destination: BlobDestinationId): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new Error(`${destination} returned an invalid response`);
}
return value as Record<string, unknown>;
}
async function jsonResponse(response: Response, destination: BlobDestinationId): Promise<Record<string, unknown>> {
await expectOk(response, destination);
let value: unknown;
try {
value = await response.json();
} catch {
throw new Error(`${destination} returned invalid JSON`);
}
return responseRecord(value, destination);
}
function nestedRecord(
record: Record<string, unknown>,
key: string,
destination: BlobDestinationId,
): Record<string, unknown> {
return responseRecord(record[key], destination);
}
function requiredString(record: Record<string, unknown>, key: string, destination: BlobDestinationId): string {
const value = record[key];
if (typeof value !== "string" || value.length === 0) {
throw new Error(`${destination} response did not include ${key}`);
}
return value;View on GitHub (pinned to 9690622007)
Solutions
- Inspect the raw body with response.text() to confirm what the host sent
- Check the host's status page or API changelog for endpoint changes
- Verify credentials and endpoint URL are current for the failing destination
- Add a fallback uploader so a single host's bad response doesn't abort the upload
Defensive patterns
Strategy: try-catch
Validate before calling
const body = await response.text(); JSON.parse(body); // fail early with the raw body visible if it is not JSON
Try / catch
try {
return await broker.publish(request);
} catch (err) {
if (err.message.endsWith("returned invalid JSON")) {
logger.warn("image host returned non-JSON success response", { destination });
return null;
}
throw err;
} Prevention
- Capture response.text() before .json() so failed bodies are inspectable
- Watch for hosts serving HTML maintenance pages with 200 status
- Configure fallback destinations in the blob broker
- Monitor host status pages for API/CDN incidents
When it happens
Trigger: Response has status 2xx but body is HTML or empty; body is malformed/truncated JSON; response.json() throws due to content encoding issues.
Common situations: Image host returning an HTML maintenance page with 200; proxy/CDN stripping the body; API deprecation redirecting to an HTML page; network interruption truncating the response.
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- ${destination} returned an invalid response
- Output {output_id} is not valid JSON: {e}
- Failed to parse marketplace catalog at ${filePath}: ${(err a
- Replacement text is not valid UTF-8: {err}
- transparent (brush_parser::BindingParseError)
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/187ede51eb77edc5.
Report an issue: GitHub.