{"record":{"id":"8a33d7d5e9248251","repo":"ChatGPTNextWeb/NextChat","slug":"failed-to-query-usage-from-openai","errorCode":null,"errorMessage":"Failed to query usage from openai","messagePattern":"Failed to query usage from openai","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app/client/platforms/openai.ts","lineNumber":464,"sourceCode":"          `${OpenaiPath.UsagePath}?start_date=${startDate}&end_date=${endDate}`,\n        ),\n        {\n          method: \"GET\",\n          headers: getHeaders(),\n        },\n      ),\n      fetch(this.path(OpenaiPath.SubsPath), {\n        method: \"GET\",\n        headers: getHeaders(),\n      }),\n    ]);\n\n    if (used.status === 401) {\n      throw new Error(Locale.Error.Unauthorized);\n    }\n\n    if (!used.ok || !subs.ok) {\n      throw new Error(\"Failed to query usage from openai\");\n    }\n\n    const response = (await used.json()) as {\n      total_usage?: number;\n      error?: {\n        type: string;\n        message: string;\n      };\n    };\n\n    const total = (await subs.json()) as {\n      hard_limit_usd?: number;\n    };\n\n    if (response.error && response.error.type) {\n      throw Error(response.error.message);\n    }\n","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/ChatGPTNextWeb/NextChat/blob/defdcdb55d850cd12c4c657eb83729fd66e215c0/app/client/platforms/openai.ts#L446-L482","documentation":"Thrown at openai.ts:464 when either the 'used' or 'subs' fetch to OpenAI's billing endpoints returns a non-2xx status (not .ok), after the 401 check has already passed. The two endpoints are dashboard/billing/usage and dashboard/billing/subscription, both of which OpenAI deprecated and removed from api.openai.com, so against the real API this almost always fires on 404/410 regardless of a valid key.","triggerScenarios":"Any non-401 failure status from GET dashboard/billing/usage or GET dashboard/billing/subscription: 404 (endpoints removed from api.openai.com), 429 rate limit, 500/502/503 server error, a proxy that returns 4xx for unknown paths, or a network-layer failure that still resolves to a Response with ok=false.","commonSituations":"Hitting the official api.openai.com — the dashboard/billing/* routes were retired, so .ok is always false; a third-party OpenAI-compatible proxy that does not implement the billing routes; rate-limited account; transient 5xx during an OpenAI incident; CORS or proxy returning an HTML error page with status 200 but body that fails JSON.parse later.","solutions":["If querying the real api.openai.com, stop relying on dashboard/billing/* — they are removed; guard with a 404 check and return an 'unavailable' usage object instead of throwing.","If behind a proxy, confirm the proxy implements the billing/usage and billing/subscription routes or disable the usage panel.","Add per-response status logging (used.status, subs.status) so the actual failure code is visible instead of a generic message.","Handle 429 with backoff/retry and surface a 'rate limited' message rather than the generic failure.","Wrap the whole usage() call in the caller so a failure degrades gracefully (hide the usage widget) instead of blocking the UI."],"exampleFix":"// before\nif (!used.ok || !subs.ok) {\n  throw new Error(\"Failed to query usage from openai\");\n}\n\n// after\nif (!used.ok || !subs.ok) {\n  const code = !used.ok ? used.status : subs.status;\n  if (code === 404) {\n    // billing endpoints not supported by this provider/proxy\n    return { used: undefined, total: undefined } as LLMUsage;\n  }\n  throw new Error(`Failed to query usage from openai (status ${code})`);\n}","handlingStrategy":"fallback","validationCode":"const isBillingSupported = (baseUrl: string): boolean => {\n  // official api.openai.com removed dashboard/billing/*; only proxies that implement them qualify\n  return !/api\\.openai\\.com/.test(baseUrl);\n};\n\nif (isBillingSupported(baseUrl)) {\n  const usage = await openai.usage();\n} else {\n  return { used: undefined, total: undefined };\n}","typeGuard":"function isUsageEndpointRemoved(res: Response): boolean {\n  return res.status === 404 || res.status === 410;\n}","tryCatchPattern":"try {\n  return await openai.usage();\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith(\"Failed to query usage\")) {\n    // degrade: hide the usage widget instead of erroring\n    return { used: undefined, total: undefined };\n  }\n  throw e;\n}","preventionTips":["Do not call dashboard/billing/* against api.openai.com — they are removed.","Log used.status and subs.status on failure to identify 404 vs 429 vs 5xx.","Make the usage panel optional so a billing failure never blocks chat."],"tags":["openai","billing","network","deprecated-api","http-status"],"backgroundTag":null,"analyzedSha":"defdcdb55d850cd12c4c657eb83729fd66e215c0","analyzedAt":"2026-08-12T09:57:26.489Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}