mastra-ai/mastra · error

Failed to fetch Copilot models: ${response.status} ${respons

Error message

Failed to fetch Copilot models: ${response.status} ${response.statusText}: ${text}

What it means

fetchCopilotModels calls the GitHub Copilot models API (the /models endpoint) and, when the HTTP response is not ok, includes the status, statusText, and response body text in this error. It surfaces upstream API failures (auth token problems, wrong endpoint, rate limits, server errors) to the caller.

Source

Thrown at mastracode/sdk/src/auth/providers/github-copilot.ts:478

 */
export async function fetchCopilotModels(opts: {
  baseUrl: string;
  bearerToken: string;
  signal?: AbortSignal;
}): Promise<CopilotModelEntry[]> {
  const url = `${opts.baseUrl.replace(/\/$/, '')}/models`;
  const response = await fetch(url, {
    headers: {
      Accept: 'application/json',
      Authorization: `Bearer ${opts.bearerToken}`,
      ...COPILOT_HEADERS,
    },
    signal: opts.signal,
  });

  if (!response.ok) {
    const text = await response.text().catch(() => '');
    throw new Error(`Failed to fetch Copilot models: ${response.status} ${response.statusText}: ${text}`);
  }

  const json = await response.json().catch(() => null);
  if (!json || typeof json !== 'object' || !Array.isArray((json as { data?: unknown }).data)) {
    throw new Error('Invalid Copilot models response: missing `data` array');
  }

  const data = (json as { data: unknown[] }).data;
  const result: CopilotModelEntry[] = [];

  for (const item of data) {
    if (!item || typeof item !== 'object') continue;
    const obj = item as Record<string, unknown>;

    if (obj.model_picker_enabled !== true) continue;

    const policy = obj.policy as Record<string, unknown> | undefined;
    if (policy && policy.state === 'disabled') continue;

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Read the embedded status/body: 401 → re-run login() to refresh the Copilot token; 403 → verify your account has an active Copilot subscription
  2. Retry after checking https://www.githubstatus.com if the status is 5xx
  3. Verify the API base URL / enterprise domain configuration used by the provider
  4. Check corporate proxy/VPN interference with api.github.com / api.individual.githubcopilot.com

Example fix

// before
const models = await provider.models(); // throws on stale token
// after
let models;
try {
  models = await provider.models();
} catch (err) {
  if (String(err.message).includes('401')) await login('github-copilot');
  models = await provider.models();
}
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight: verify credentials are present and fresh before calling models()
const creds = await loadCredentials();
if (!creds || creds.expires <= Date.now()) {
  await login('github-copilot'); // refresh before hitting the models API
}

Type guard

function isModelsHttpError(err: unknown): err is Error & { status?: number } {
  const m = err instanceof Error ? err.message.match(/Failed to fetch Copilot models: (\d{3})/) : null;
  return m !== null;
}

Try / catch

try {
  models = await provider.models({ signal });
} catch (err) {
  const m = err instanceof Error && err.message.match(/Failed to fetch Copilot models: (\d{3})/);
  if (m && (m[1] === '429' || m[1].startsWith('5'))) {
    await backoff(); models = await provider.models({ signal }); // retry transient failures
  } else if (m && m[1] === '401') {
    await login('github-copilot'); models = await provider.models({ signal });
  } else throw err;
}

Prevention

When it happens

Trigger: The Copilot API returns a non-2xx status: expired/invalid Copilot token (401), missing Copilot subscription/entitlement (403), wrong API base URL or enterprise domain, or 5xx outages. Called via provider.models() with valid stored credentials otherwise.

Common situations: Token expired after long idle; account lost Copilot access; self-hosted proxy or enterprise domain misconfigured; GitHub API incident/rate limit; network path through a corporate proxy returning HTML error pages.

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


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/6ee78ca5aa335eab. Report an issue: GitHub.