can1357/oh-my-pi · error · AIError.ProviderHttpError
HTTP request failed. status=${response.status}; url=${url};
Error message
HTTP request failed. status=${response.status}; url=${url}; body=${responseBody} What it means
getJson performs a GET against a Z.ai business endpoint with a 30s timeout and throws AIError.ProviderHttpError when the HTTP status is not ok, including the status, URL, and raw response body. This is a transport/HTTP-level failure surfaced from the Z.ai REST API.
Source
Thrown at packages/ai/src/registry/oauth/zai.ts:77
throw new AIError.OAuthError(`Z.ai ${operation} failed: ${envelope.msg ?? `code ${String(envelope.code)}`}`, {
kind: "token-exchange",
provider: "zai",
});
}
return "data" in envelope ? envelope.data : envelope;
}
return body;
}
async function getJson(url: string, headers: Record<string, string>, fetchImpl: FetchImpl): Promise<unknown> {
const response = await fetchImpl(url, {
method: "GET",
headers,
signal: AbortSignal.timeout(30_000),
});
const responseBody = await response.text();
if (!response.ok) {
throw new AIError.ProviderHttpError(
`HTTP request failed. status=${response.status}; url=${url}; body=${responseBody}`,
response.status,
);
}
return responseBody.length > 0 ? JSON.parse(responseBody) : undefined;
}
async function postJson(
url: string,
body: Record<string, string | number>,
headers: Record<string, string>,
fetchImpl: FetchImpl,
): Promise<unknown> {
const response = await fetchImpl(url, {
method: "POST",
headers: { ...headers, "Content-Type": "application/json" },
body: JSON.stringify(body),
signal: AbortSignal.timeout(30_000),View on GitHub (pinned to 9690622007)
Solutions
- Inspect status and body in the ProviderHttpError: 401/403 → refresh the business token via business login; 404 → verify organizationId/projectId/apiKey; 429/5xx → back off and retry.
- Re-authenticate the Z.ai business token and retry the GET.
- Confirm the correct regional BIZ_BASE URL for the account.
- Wrap calls in retry with exponential backoff for transient 429/5xx statuses.
Example fix
// before
const orgs = await getJson(ORGS_URL, auth, fetch);
// after
let orgs;
try { orgs = await getJson(ORGS_URL, auth, fetch); }
catch (e) {
if (e instanceof AIError.ProviderHttpError && (e.status === 429 || e.status >= 500)) { await Bun.sleep(1000); orgs = await getJson(ORGS_URL, auth, fetch); }
else throw e;
} Defensive patterns
Strategy: retry
Validate before calling
if (!bizToken || typeof bizToken !== "string") throw new Error("Refusing GET: missing Z.ai business token"); Try / catch
try { return await getJson(url, auth, fetch); }
catch (e) {
if (e instanceof AIError.ProviderHttpError && (e.status === 429 || e.status >= 500) && attempt < 3) { await Bun.sleep(2 ** attempt * 500); return retry(); }
throw e;
} Prevention
- Refresh the business token before it expires
- Retry only 429/5xx with backoff; fail fast on 401/403/404
- Log status+body from ProviderHttpError for diagnosis
- Verify regional endpoint URLs in configuration
When it happens
Trigger: GET to org/project list or api key copy endpoint returns 401/403/404/429/5xx; the copy endpoint path contains a malformed apiKey; auth headers carry an invalid biz token; network middleboxes return error pages.
Common situations: Expired business token causing 401; wrong BIZ_BASE region host; Z.ai API returns 429 under rate limiting; copy endpoint 404 because the key was deleted concurrently.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- ${operation} failed: ${typeof details === "string" ? details
- V2 remote compaction failed (${response.status} ${response.s
- sso-role
- Devin API error ${response.status} ${response.statusText}: $
- ${response.status} ${response.statusText}: ${text}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/f39f10b767583015.
Report an issue: GitHub.