twentyhq/twenty · error · RestApiClientError
Request to ${url} failed with status ${response.status} ${re
Error message
Request to ${url} failed with status ${response.status} ${response.statusText} What it means
Thrown by RestApiClient.parseResponse (rest/index.ts:328-337) as a RestApiClientError when `response.ok` is false. Unlike the GraphQL path, this includes structured details (status, statusText, url, body) on the error object. The body is JSON.parsed when possible, otherwise kept as raw text.
Source
Thrown at packages/twenty-client-sdk/src/rest/index.ts:329
}
private async parseResponse<TResponse>(
response: Response,
url: string,
): Promise<TResponse> {
const rawBody = await response.text();
let parsedBody: unknown = undefined;
if (rawBody.trim().length > 0) {
try {
parsedBody = JSON.parse(rawBody);
} catch {
parsedBody = rawBody;
}
}
if (!response.ok) {
throw new RestApiClientError(
`Request to ${url} failed with status ${response.status} ${response.statusText}`,
{
status: response.status,
statusText: response.statusText,
url,
body: parsedBody,
},
);
}
return parsedBody as TResponse;
}
private async execute<TResponse>(
method: string,
path: string,
body: unknown,
requestOptions?: RestApiRequestOptions,View on GitHub (pinned to 1f5dd2bbd2)
Solutions
- Catch RestApiClientError and read `err.status`, `err.body`, and `err.url` for diagnosis.
- For 401, refresh the token and retry (or register the host refresh hook).
- For 404, verify the path and resource id; for 400, validate the body shape against the API.
- For 5xx, check Twenty server logs and retry with backoff.
Example fix
// before
await client.post('/rest/objects/contact', payload);
// after
try {
await client.post('/rest/objects/contact', payload);
} catch (err) {
if (err instanceof RestApiClientError) {
console.error(err.status, err.body);
}
throw err;
} Defensive patterns
Strategy: try-catch
Type guard
const isRestApiClientError = (e: unknown): e is RestApiClientError => e instanceof RestApiClientError;
Try / catch
try {
const result = await client.post('/rest/objects/contact', payload);
} catch (err) {
if (err instanceof RestApiClientError) {
// err.status, err.statusText, err.url, err.body are all available
if (err.status === 401) await refreshToken();
else if (err.status === 404) console.error('Not found:', err.url);
else console.error('Request failed:', err.status, err.body);
}
throw err;
} Prevention
- Always catch RestApiClientError and branch on err.status.
- Validate request bodies and ids before sending to avoid 400/404.
- Refresh tokens proactively before expiry to avoid 401s.
- Retry 5xx with exponential backoff.
When it happens
Trigger: Any REST method (get/post/put/patch/delete) where the server returns a non-2xx status: 400 for validation, 401 for auth, 403 forbidden, 404 not found, 5xx server error.
Common situations: Wrong path or REST resource id (404); insufficient permissions (403); malformed body (400); expired token (401); server error (500); rate limiting (429).
Related errors
- ${res.statusText}: ${await res.text()}
- ${response.statusText}: ${response.rawBody}
- Invalid JSON response
- Missing API url. Set the `${DEFAULT_API_URL_NAME}` environme
- Missing application access token. Set the `${DEFAULT_APP_ACC
AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12).
Data as JSON: /api/errors/c63498d26bf1bb5f.
Report an issue: GitHub.