twentyhq/twenty · error · Error
Server error (${response.status})
Error message
Server error (${response.status}) What it means
callAppRoute POSTs JSON to a Twenty app route (TWENTY_FUNCTIONS_URL or TWENTY_API_URL/s<path>) and, on a non-ok response, extracts a message. 'Server error (status)' is the FALLBACK string used only when the response body is not parseable JSON or the parsed JSON lacks any of messages/message/error. So this exact text means the server returned an error status with an unstructured (often non-JSON) body.
Source
Thrown at packages/twenty-apps/internal/twenty-partners/src/modules/shared/front-components/call-app-route.ts:40
): Promise<unknown> => {
const token = process.env.TWENTY_APP_ACCESS_TOKEN;
const functionsUrl = process.env.TWENTY_FUNCTIONS_URL;
const apiUrl = process.env.TWENTY_API_URL ?? '';
const normalizedPath = path.startsWith('/') ? path : `/${path}`;
const url = functionsUrl ? `${functionsUrl}${normalizedPath}` : `${apiUrl}/s${normalizedPath}`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
body: JSON.stringify(body),
});
if (!response.ok) {
throw new Error(await extractErrorMessage(response));
}
return response.json();
};
View on GitHub (pinned to 1f5dd2bbd2)
Solutions
- Verify TWENTY_FUNCTIONS_URL / TWENTY_API_URL / TWENTY_APP_ACCESS_TOKEN are set and the URL resolves to the Twenty workspace.
- Confirm the target app route is deployed and registered at the given path.
- Reproduce the POST with curl -i to see the raw status and body (HTML vs JSON).
- If the body is HTML from a gateway, check the functions/hosting platform health.
Example fix
// before
if (!response.ok) {
throw new Error(await extractErrorMessage(response));
}
// after — include the URL and status code in the fallback so the cause is diagnosable
if (!response.ok) {
const message = await extractErrorMessage(response);
throw new Error(`${message} (url=${url}, status=${response.status})`);
} Defensive patterns
Strategy: try-catch
Validate before calling
function assertCallAppRouteEnv() {
const functionsUrl = process.env.TWENTY_FUNCTIONS_URL;
const apiUrl = process.env.TWENTY_API_URL;
if (!functionsUrl && !apiUrl) {
throw new Error('Set TWENTY_FUNCTIONS_URL or TWENTY_API_URL before calling app routes');
}
if (!process.env.TWENTY_APP_ACCESS_TOKEN) {
throw new Error('Set TWENTY_APP_ACCESS_TOKEN before calling app routes');
}
}
await assertCallAppRouteEnv(); Try / catch
try {
return await callAppRoute('/my-route', body);
} catch (err) {
// 'Server error (status)' means the body was non-JSON or lacked an error field.
// Reproduce with curl -i against the same URL/token to see the raw body.
throw new Error(`callAppRoute failed: ${err instanceof Error ? err.message : String(err)}`);
} Prevention
- Always set TWENTY_FUNCTIONS_URL (or TWENTY_API_URL) and TWENTY_APP_ACCESS_TOKEN.
- Confirm the app route is deployed and registered at the path before calling.
- Reproduce failures with curl -i to inspect raw status/body (HTML vs JSON).
- Treat a non-JSON error body as a gateway/deployment problem, not an app logic error.
When it happens
Trigger: response.ok is false AND extractErrorMessage could not find a structured error field. Happens when a gateway/proxy returns HTML (502/503/504), the app route threw an unhandled error producing a plain-text body, the URL is wrong (404 HTML page), or TWENTY_APP_ACCESS_TOKEN is missing/expired and the server returns a non-JSON auth error.
Common situations: TWENTY_FUNCTIONS_URL or TWENTY_API_URL misconfigured (trailing slash, wrong host) hitting a 404 HTML page; functions deployment down (502 from platform); token unset so auth middleware returns a non-JSON 401; app route not deployed/registered.
Related errors
- Missing env var: ${name}
- Missing ${name} env var
- Missing ${name} env var
- download failed with status ${response.status}
- createCompany did not return an id
AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12).
Data as JSON: /api/errors/1422b831ff91e8ec.
Report an issue: GitHub.