tinyhumansai/openhuman · error
HTTP error! status: ${response.status}
Error message
HTTP error! status: ${response.status} What it means
Thrown by the generic fetch wrapper in apiClient when the response is NOT ok AND the content-type is not application/json — the two preconditions for trying to parse a structured ApiError. Because the body is not JSON, the status code is the only information available, hence the generic template `HTTP error! status: ${response.status}`.
Source
Thrown at app/src/services/apiClient.ts:99
}
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
const config: RequestInit = { method, headers, signal: controller.signal };
if (body && method !== 'GET') {
config.body = JSON.stringify(body);
}
try {
const response = await fetch(url, config);
// Handle non-JSON responses
const contentType = response.headers.get('content-type');
if (!contentType || !contentType.includes('application/json')) {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return {} as T;
}
const data = await response.json();
// Handle error responses
if (!response.ok) {
const error: ApiError = data.error
? { success: false, error: data.error, message: data.message }
: { success: false, error: `HTTP ${response.status}: ${response.statusText}` };
throw error;
}
return data as T;
} catch (error) {
// Re-throw API errors as-is
if (error && typeof error === 'object' && 'error' in error) {View on GitHub (pinned to a221052e0d)
Solutions
- Read the status from the message: 502/503/504 are infra/proxy — retry shortly or check the backend status page; 404 usually means a wrong base URL
- Verify the backend URL configuration (VITE_* config via app/src/utils/config.ts / .env files) points at the real API host
- curl -i the same URL from the same machine and inspect what non-JSON body comes back and from which hop
- Retry with backoff for 5xx gateway codes — these are typically transient
- If a proxy strips JSON, fix the proxy/TLS-inspection exemption for the API host
Example fix
// before
const data = await apiClient.request<T>('/teams');
// after
try {
const data = await apiClient.request<T>('/teams');
} catch (e) {
if (e instanceof Error && /HTTP error! status: 5\d\d/.test(e.message)) {
return retryWithBackoff(() => apiClient.request<T>('/teams'));
}
throw e;
} Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight connectivity sanity: an infra/proxy error page usually fails a cheap probe too
const ok = await fetch(baseUrl, { method: 'HEAD' }).then(r => r.ok).catch(() => false);
if (!ok) skipCloudCallAndWarn(); Type guard
function isNonJsonHttpError(e: unknown): e is Error {
return e instanceof Error && /HTTP error! status: \d+/.test(e.message);
} Try / catch
try {
return await api.request<T>(path, init);
} catch (e) {
const status = e instanceof Error ? Number(/status: (\d+)/.exec(e.message)?.[1]) : 0;
if (status >= 500 && attempt < 3) {
await delay(2 ** attempt * 500);
return api.request<T>(path, init); // gateway errors are usually transient
}
if (status === 404) throw new Error(`API base URL may be wrong: ${baseUrl}`);
throw e;
} Prevention
- Validate the backend base URL at startup with a HEAD/OPTIONS probe and fail with a clear message
- Distinguish infra-status (5xx from proxies) from API-status (JSON {success:false}) in error handling
- Watch for HTML content-types in monitoring — they betray proxy/TLS interference early
When it happens
Trigger: The cloud backend (or anything in front of it) returns an HTML error page with 502/503/504 (CDN/proxy like Cloudflare, maintenance page, gateway timeout), a plain-text 500 from an infra component, or the configured base URL points at a server that is not the API at all.
Common situations: Backend outage or deploy window surfaced as proxy HTML; wrong BACKEND/API base URL in app config or .env (hitting a marketing site or empty host); corporate TLS-inspection proxy replacing responses; backend returning empty bodies on 5xx.
Related errors
- Failed to send magic link (${response.status})
- [transport:cloud] HTTP ${response.status}: ${text || respons
- [transport:lan] HTTP ${response.status}: ${text || response.
- Request timed out. Please try again.
- Core RPC HTTP ${response.status}: ${text || response.statusT
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/7d40963b244955c9.
Report an issue: GitHub.