can1357/oh-my-pi · error · ApiError
HTTP error ${res.status} on ${endpoint}
Error message
HTTP error ${res.status} on ${endpoint} What it means
fetchJson() in the omp stats dashboard client wraps every REST call and throws ApiError when the HTTP response status is not ok (anything outside 2xx). The error carries the status code and the endpoint so the UI layer can distinguish server failures from bad requests. It applies to all stats fetches: overview, dashboards, recent requests/errors, and request details.
Source
Thrown at packages/stats/src/client/api.ts:32
const API_BASE = "/api";
export class ApiError extends Error {
status: number;
endpoint: string;
constructor(status: number, endpoint: string, message: string) {
super(message);
this.name = "ApiError";
this.status = status;
this.endpoint = endpoint;
}
}
async function fetchJson<T>(endpoint: string, options?: RequestInit): Promise<T> {
const res = await fetch(endpoint, options);
if (!res.ok) {
throw new ApiError(res.status, endpoint, `HTTP error ${res.status} on ${endpoint}`);
}
return res.json() as Promise<T>;
}
export async function getOverviewStats(range: TimeRange = "24h", signal?: AbortSignal): Promise<OverviewStats> {
return fetchJson<OverviewStats>(`${API_BASE}/stats/overview?range=${encodeURIComponent(range)}`, {
signal,
});
}
export async function getModelDashboardStats(
range: TimeRange = "24h",
signal?: AbortSignal,
): Promise<ModelDashboardStats> {
return fetchJson<ModelDashboardStats>(`${API_BASE}/stats/model-dashboard?range=${encodeURIComponent(range)}`, {
signal,
});
}View on GitHub (pinned to 9690622007)
Solutions
- Check the stats server is running and reachable at API_BASE (curl the endpoint to see the real status/body)
- Retry with backoff if the server was booting (transient 502/503)
- Verify API_BASE and endpoint paths match the running server version
- Inspect the ApiError.status to branch: 404 → version mismatch/wrong base URL; 5xx → server-side failure; 4xx → bad parameters
Example fix
// before
const stats = await getOverviewStats(range); // throws ApiError on 500
// after
try {
const stats = await getOverviewStats(range);
} catch (err) {
if (err instanceof ApiError && (err.status === 502 || err.status === 503)) {
stats = await withRetry(() => getOverviewStats(range));
} else throw err;
} Defensive patterns
Strategy: retry
Validate before calling
const res = await fetch(`${API_BASE}/stats/overview?range=${range}`, { method: 'HEAD' });
if (!res.ok) console.warn(`Stats API unhealthy: ${res.status}`); Type guard
function isApiError(err: unknown): err is ApiError {
return err instanceof ApiError;
} Try / catch
try {
const stats = await getOverviewStats(range, signal);
} catch (err) {
if (err instanceof ApiError && err.status >= 500) {
// transient — retry with backoff
} else if (err instanceof ApiError && err.status === 404) {
// version/base-URL mismatch — surface a config hint
} else throw err;
} Prevention
- Health-check the stats server before polling the dashboard endpoints
- Branch on ApiError.status rather than treating all failures alike
- Keep API_BASE and the client bundle versions in sync with the server
- Pass an AbortSignal so stale requests do not pile up during outages
When it happens
Trigger: Any exported fetcher (getOverviewStats, getModelDashboardStats, getCostDashboardStats, getRecentRequests, getRecentErrors, getRequestDetails) receiving a 4xx/5xx response — server not running or crashed, wrong API_BASE, range parameter rejected, endpoint changed between versions, or a proxy returning 404/502.
Common situations: The omp stats server was restarted or is still booting while the dashboard polls; hitting an old cached bundle pointed at a removed endpoint; a reverse proxy answering 502 because the upstream stats server died; invalid TimeRange value producing a 400.
Related errors
- ${response.status} ${response.statusText}: ${text}
- Failed to fetch marketplace catalog from ${source}: HTTP ${r
- Failed to fetch item ${itemId}
- V2 remote compaction failed (${response.status} ${response.s
- AnthropicConnectionError
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/46a7691a8c0a54a4.
Report an issue: GitHub.