can1357/oh-my-pi · error · AIError.ProviderHttpError

Invalid Copilot usage response

Error message

Invalid Copilot usage response

What it means

Thrown when GitHub's /copilot_internal/user endpoint returns HTTP 200 but the JSON body is not a plain object, so it cannot be shaped into CopilotUsageResponse. The library validates the envelope (isRecord) before casting and refuses to continue with an unusable payload. The 200 status passed to ProviderHttpError signals the failure was payload-shaped, not transport-level.

Source

Thrown at packages/ai/src/usage/github-copilot.ts:187

	} catch {
		return undefined;
	}
}

async function fetchInternalUsage(
	ctx: UsageFetchContext,
	githubApiBaseUrl: string,
	token: string,
	signal?: AbortSignal,
): Promise<CopilotUsageResponse> {
	const headers: Record<string, string> = {
		"Content-Type": "application/json",
		Accept: "application/json",
		Authorization: `Bearer ${token}`,
		...OPENCODE_HEADERS,
	};
	const data = await fetchJson(ctx, `${githubApiBaseUrl}/copilot_internal/user`, { headers, signal });
	if (!isRecord(data)) throw new AIError.ProviderHttpError("Invalid Copilot usage response", 200);
	return data as CopilotUsageResponse;
}

async function fetchBillingUsage(
	ctx: UsageFetchContext,
	baseUrl: string,
	username: string,
	token: string,
	signal?: AbortSignal,
): Promise<BillingUsageResponse> {
	const data = await fetchJson(
		ctx,
		`${baseUrl}/users/${encodeURIComponent(username)}/settings/billing/premium_request/usage`,
		{
			headers: {
				Accept: "application/vnd.github+json",
				Authorization: `Bearer ${token}`,
				"X-GitHub-Api-Version": "2022-11-28",

View on GitHub (pinned to 9690622007)

Solutions

  1. Log or capture the actual response body to see what replaced the expected JSON object.
  2. Verify the GitHub API base URL points at api.github.com (or a transparent JSON proxy), not an HTML-serving gateway.
  3. Re-authenticate behind SSO/proxies — complete any pending device or browser login flow.
  4. Update the library if GitHub changed the internal endpoint shape; check for a newer version.

Example fix

// before: custom proxy base URL that serves HTML on 200
baseUrl = "https://gateway.corp.internal/github";
// after: use the real GitHub API endpoint
baseUrl = "https://api.github.com";
Defensive patterns

Strategy: type-guard

Type guard

function isRecord(v: unknown): v is Record<string, unknown> {
	return typeof v === "object" && v !== null && !Array.isArray(v);
}
// pre-validate the same shape the library checks
const data: unknown = await res.json();
if (!isRecord(data)) throw new Error("Copilot usage endpoint returned non-object JSON");

Try / catch

try {
	const usage = await copilot.usage(params);
} catch (err) {
	if (err instanceof AIError.ProviderHttpError && err.message === "Invalid Copilot usage response") {
		logger.warn("Copilot usage: non-JSON/proxied 200 response — check network path");
	} else throw err;
}

Prevention

When it happens

Trigger: fetchInternalUsage receives a 200 response whose parsed JSON is null, an array, a string, or a number instead of an object — typically when an auth proxy, login page, or HTML error interstitial is served instead of the real JSON, or GitHub changes the internal endpoint's response shape.

Common situations: Corporate SSO proxy returning an HTML redirect/login page with status 200; captive portal Wi-Fi; hitting a mirror/base URL that is not the real GitHub API; GitHub changing the undocumented copilot_internal response contract.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/4be5fbc1f3618423. Report an issue: GitHub.