can1357/oh-my-pi · error · AIError.OAuthError
Z.ai ${operation} failed: ${envelope.msg ?? `code ${String(e
Error message
Z.ai ${operation} failed: ${envelope.msg ?? `code ${String(envelope.code)}`} What it means
Z.ai API responses arrive wrapped in an envelope ({code, msg, data} or {success,...}). unwrapEnvelope treats success===false or a non-success code as an application-level failure and throws OAuthError tagged kind=token-exchange, provider=zai, embedding the server's msg (or raw code). This is the server saying the operation itself failed, distinct from transport errors.
Source
Thrown at packages/ai/src/registry/oauth/zai.ts:59
/**
* Z.ai's `{ code, msg, data, success }` envelope. The OAuth token endpoint
* signals success with `code: 0`; the biz endpoints (`api.z.ai`) use
* `code: 200` / `success: true`. Accept both; throw `msg` on failure. Bodies
* without a status wrapper pass through unchanged.
*/
function isSuccessCode(code: unknown): boolean {
if (code == null) return true;
if (typeof code === "number") return code === 0 || code === 200;
if (typeof code === "string") return code === "0" || code === "200";
return false;
}
function unwrapEnvelope(body: unknown, operation: string): unknown {
if (body && typeof body === "object" && ("code" in body || "success" in body)) {
const envelope = body as { code?: unknown; msg?: string; data?: unknown; success?: unknown };
if (envelope.success === false || !isSuccessCode(envelope.code)) {
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(View on GitHub (pinned to 9690622007)
Solutions
- Read envelope.msg in the thrown error for the server's reason and fix accordingly (usually re-auth to get a fresh oauth token).
- Re-run the Z.ai OAuth login flow to obtain a new access token, then retry minting the key.
- Verify the Z.ai account actually has an organization and default project before exchange.
- Catch AIError.OAuthError and inspect the message/kind to distinguish auth problems from provisioning problems.
Example fix
// before
const data = await postJson(BUSINESS_LOGIN_URL, { token: staleAccessToken }, {}, fetch);
// after
try { const data = await postJson(BUSINESS_LOGIN_URL, { token: freshAccessToken }, {}, fetch); }
catch (e) { if (e instanceof AIError.OAuthError) await reloginZai(); throw e; } Defensive patterns
Strategy: try-catch
Type guard
function isZaiFailureEnvelope(b: unknown): boolean { return !!b && typeof b === "object" && (("code" in b && Number((b as any).code) !== 200) || (b as any).success === false); } Try / catch
try { const biz = await exchangeZaiToken(oauthToken); }
catch (e) {
if (e instanceof AIError.OAuthError && e.message.includes("Z.ai")) {
logger.warn("Z.ai exchange rejected", { msg: e.message });
return reloginZai();
}
throw e;
} Prevention
- Refresh the OAuth token before starting token-exchange flows
- Pre-check account provisioning (org/project exists) before exchange
- Surface envelope.msg from the error to the user instead of a generic message
When it happens
Trigger: Any Z.ai business-API call whose body carries success:false or a failure code: business login with an invalid/expired oauth token, org/project listing denied for the account, api key create/copy rejected (quota, permissions, name conflict).
Common situations: OAuth access token expired between login and exchange; account lacks organization/project provisioning; Z.ai-side rate limits or permission errors; API version changes altering the code semantics.
Related errors
- Z.ai business login returned no access token
- GitLab OAuth token exchange failed: ${response.status} ${awa
- Token exchange failed: ${formatOpenAICodexTokenEndpointError
- Token exchange failed: ${response.status} ${errorText}
- Token exchange returned no access token${providerError ? `:
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/e6470b6e68e1ba64.
Report an issue: GitHub.