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

  1. Log responseText before parsing to see exactly what was returned on a 200.
  2. Check whether the body is HTML (login/consent/proxy page) and address the redirect/auth issue at that layer.
  3. Ensure the request sends Accept: application/json (this helper already does) and that the provider supports JSON output.
  4. If the format changed, update the parsing logic to match the provider's current schema.
  5. 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

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.

Related errors


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)