ellite/Wallos · error · Error
Invalid JSON response
Error message
Invalid JSON response
What it means
In the same helper, after a successful HTTP response the body is read as text and JSON.parse'd; a parse failure throws 'Invalid JSON response'. The server returned 2xx but the body is not valid JSON — commonly an HTML interstitial, empty body, or garbled/encoding-broken payload. The helper's catch block may retry the request once for transient cases.
Solutions
- Log responseText before parsing to see exactly what was returned on a 200.
- Check whether the body is HTML (login/consent/proxy page) and address the redirect/auth issue at that layer.
- Ensure the request sends Accept: application/json (this helper already does) and that the provider supports JSON output.
- If the format changed, update the parsing logic to match the provider's current schema.
- For intermittent truncation, keep the existing retry but add a small delay/backoff.
Example fix
// before
try {
return JSON.parse(body);
} catch (error) {
throw new Error("Invalid JSON response");
}
// after
try {
return JSON.parse(body);
} catch (error) {
throw new Error(`Invalid JSON response: ${body.slice(0, 120)}`);
} Defensive patterns
Strategy: retry
Validate before calling
function isLikelyJson(text) {
const t = (text ?? '').trim();
return t.length > 0 && !/^\s*<!doctype html/i.test(t) && (t.startsWith('{') || t.startsWith('['));
} Try / catch
fetchSourceData(url).catch(err => {
if (err.message === 'Invalid JSON response') {
return fetchSourceData(url, /* retry */ true); // helper retries once; add backoff
}
throw err;
}); Prevention
- Send Accept: application/json on every source request and confirm the provider honors it.
- Log response bodies (truncated) when parse fails to detect HTML injection or format changes.
- Handle transient truncation with a single delayed retry (the helper already supports this).
- Monitor providers for response-format changes and pin/adapter your parser accordingly.
When it happens
Trigger: response.text() yields non-JSON content despite 2xx: an HTML page served with 200 (captive portal, wrong URL, consent wall), empty response body, truncated or encoding-corrupted JSON, or the provider sending plain text/CSV where JSON was expected.
Common situations: Proxies or firewalls injecting HTML into 200 responses; provider quietly changing its response format; intermittent network truncation (mitigated by the helper's built-in retry); Accept header not honored so the server returns HTML.
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
- ` (HTTP )
- translate("network_response_error")
- translate("network_response_error")
- HTTP
- $this->lang('smtp_connect_failed')
AI-assisted analysis of ellite/Wallos@52820e87ca (2026-09-13).
Data as JSON: /api/errors/6a8ebf3fc73bf0b2.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/subscriptions.js:463
});
}
function fetchLogoSearchSource(url, retry = true) {
return fetch(url, {
cache: "no-store",
headers: { "Accept": "application/json" },
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.text();
})
.then(body => {
try {
return JSON.parse(body);
} catch (error) {
throw new Error("Invalid JSON response");
}
})
.catch(error => {
if (retry) {
// Wait a moment before retrying: sources like Brave rate-limit
// aggressively, and retrying instantly just repeats the failure.
return new Promise(resolve => setTimeout(resolve, 600))
.then(() => fetchLogoSearchSource(url, false));
}
throw error;
});
}
function displayImageResults(imageSources, container) {
container.innerHTML = "";
imageSources.forEach(src => {
const img = document.createElement("img");
View on GitHub (pinned to 52820e87ca)