jackwener/OpenCLI · error · Error
invalid JSON from ${requestUrl}: ${error.message}
Error message
invalid JSON from ${requestUrl}: ${error.message} What it means
The fetch helper JSON-parses the response body and, if JSON.parse throws, re-throws an Error naming the URL and the parser's message. It guards against TikTok returning HTML (login walls, captchas, error pages) or truncated bodies where JSON was expected.
Source
Thrown at clis/tiktok/utils.js:244
}
return '';
}
async function fetchJson(url) {
const requestUrl = new URL(url, ${JSON.stringify(TIKTOK_HOST)}).toString();
const res = await fetch(requestUrl, {
credentials: 'include',
headers: { accept: 'application/json,text/plain,*/*' },
});
const text = await res.text();
if (!res.ok) {
throw new Error('HTTP ' + res.status + ' from ' + requestUrl + ': ' + text.slice(0, 160));
}
if (!text.trim()) return {};
try {
return JSON.parse(text);
} catch (error) {
throw new Error('invalid JSON from ' + requestUrl + ': ' + (error instanceof Error ? error.message : String(error)));
}
}
function assertTikTokApiSuccess(data, label) {
if (!data || typeof data !== 'object') return;
const code = data.status_code ?? data.statusCode;
if (code === undefined || code === null || Number(code) === 0) return;
const message = cleanText(data.status_msg ?? data.statusMsg ?? data.message ?? data.msg ?? code, 240);
if (Number(code) === 8 || /auth|captcha|login|permission|unauthori[sz]ed|forbidden/i.test(message)) {
throw new Error('AUTH_REQUIRED: ' + label + ' API failed: ' + message);
}
throw new Error(label + ' API failed: ' + message);
}
function findUniversalData() {
const scripts = Array.from(document.querySelectorAll('script'));
for (const script of scripts) {
const text = script.textContent || '';View on GitHub (pinned to 49907e53dc)
Solutions
- Check the JSON.parse message for the exact syntax error position — '<' at position 0 means HTML was returned
- Refresh TikTok session cookies; an HTML body usually means the session is no longer valid
- Log the raw body once to see what is actually being served
- Verify the URL wasn't redirected (check response.url) to a login page
Example fix
// before
return JSON.parse(text);
// after
if (text.trimStart().startsWith('<')) {
throw new Error('received HTML instead of JSON (likely auth wall) from ' + requestUrl);
}
return JSON.parse(text); Defensive patterns
Strategy: type-guard
Validate before calling
const res = await fetch(url, { credentials: 'include' });
const text = await res.text();
if (text.trimStart().startsWith('<')) throw new Error('got HTML (auth wall?) — refresh session'); Type guard
function isJsonString(s) { if (typeof s !== 'string') return false; try { JSON.parse(s); return true; } catch { return false; } } Try / catch
try { return JSON.parse(text); } catch (e) {
if (text.trimStart().startsWith('<')) throw new AuthRequiredError('tiktok.com', 'HTML served instead of JSON');
throw e;
} Prevention
- Inspect Content-Type before parsing
- Treat '<'-leading bodies as auth walls and refresh cookies
- Log one raw response when parsing fails
- Handle empty bodies explicitly ({} case already exists)
When it happens
Trigger: The endpoint returned 200 but a non-JSON body — typically an HTML login/captcha page, an empty-but-whitespace-only body is fine (returns {}), but any other non-JSON payload fails JSON.parse.
Common situations: Expired session redirects the API to the login HTML page; WAF serves a challenge page with 200; CDN error page returned instead of JSON; response cut off mid-body by proxy.
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
- archive search returned malformed JSON: ${error?.message ||
- archive wayback returned malformed JSON: ${error?.message ||
- ${label} returned malformed JSON: ${err?.message ?? err}
- hf models returned malformed JSON: ${error?.message || error
- ${label} returned malformed JSON: ${err?.message ?? err}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/6dcd69751cb5bb87.
Report an issue: GitHub.