twentyhq/twenty · error · Error
Invalid JSON response
Error message
Invalid JSON response
What it means
Thrown by TwentyClient.assertResponseIsSuccessful (twenty-client-template.ts:380-382) when the response status was 2xx but payload is null. payload is set to null by executeGraphqlRequest (line 341-348) when rawBody is empty or JSON.parse fails — so the body was empty or not valid JSON.
Source
Thrown at packages/twenty-client-sdk/src/generate/twenty-client-template.ts:381
return this.headers ?? {};
}
private shouldRefreshToken(response: GraphqlResponse): boolean {
if (response.status === 401) {
return true;
}
return hasAuthenticationErrorInGraphqlPayload(response.payload);
}
private assertResponseIsSuccessful(response: GraphqlResponse) {
if (response.status < 200 || response.status >= 300) {
throw new Error(`${response.statusText}: ${response.rawBody}`);
}
if (response.payload === null) {
throw new Error('Invalid JSON response');
}
return response.payload;
}
private async requestRefreshedAccessToken(): Promise<string | null> {
const refreshAccessTokenFunction = (
globalThis as {
frontComponentHostCommunicationApi?: {
requestAccessTokenRefresh?: () => Promise<string>;
};
}
).frontComponentHostCommunicationApi?.requestAccessTokenRefresh;
if (typeof refreshAccessTokenFunction !== 'function') {
return null;
}
View on GitHub (pinned to 1f5dd2bbd2)
Solutions
- Inspect response.rawBody from the surrounding context (or reproduce the request with curl) to see what the server actually returned.
- Check intermediary proxies/CDNs for HTML error pages masquerading as 200.
- Ensure the apiUrl points to the GraphQL endpoint, not a generic web route.
- Verify Accept/Content-Type negotiation with the Twenty server.
Defensive patterns
Strategy: try-catch
Try / catch
try {
const result = await client.someQuery();
} catch (err) {
if (err.message === 'Invalid JSON response') {
// Reproduce with curl to inspect the raw 2xx body returned by the gateway.
}
} Prevention
- Ensure the GraphQL endpoint returns JSON, not HTML.
- Verify intermediary proxies do not return empty 200s.
- Confirm apiUrl targets the GraphQL route.
- Test the endpoint directly with curl before integrating.
When it happens
Trigger: GraphQL endpoint returns 200 OK with an empty body, or with a non-JSON body (HTML error page, plain text). JSON.parse throws inside the try block, payload stays null, and the success assertion rejects it.
Common situations: Reverse proxy or CDN returning an empty 200 (e.g. successful CORS preflight surfacing as the response); gateway returning an HTML error page with a 200 status; backend bug returning empty body; gzip/encoding mismatch where text() yields nothing parseable.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- ${res.statusText}: ${await res.text()}
- ${response.statusText}: ${response.rawBody}
- Genql batch fetcher returned unexpected result + JSON.strin
- response length did not match query length
- Request to ${url} failed with status ${response.status} ${re
AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12).
Data as JSON: /api/errors/302c0e0bb30d05fe.
Report an issue: GitHub.