{"record":{"id":"a6069b360fe57b0b","repo":"mastra-ai/mastra","slug":"no-copilot-bearer-token","errorCode":null,"errorMessage":"No Copilot bearer token","messagePattern":"No Copilot bearer token","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"mastracode/sdk/src/providers/github-copilot.ts","lineNumber":375,"sourceCode":"  storage.reload();\n\n  const cred = storage.get(COPILOT_PROVIDER_ID);\n  if (!cred || cred.type !== 'oauth') {\n    return [];\n  }\n\n  const now = Date.now();\n  if (catalogCache && now - catalogCache.fetchedAt < catalogCache.ttl) {\n    return catalogCache.models;\n  }\n\n  if (inflightFetch) return inflightFetch;\n\n  inflightFetch = (async (): Promise<CopilotModelEntry[]> => {\n    try {\n      // getApiKey() refreshes the Copilot bearer if it has expired.\n      const accessToken = await storage.getApiKey(COPILOT_PROVIDER_ID);\n      if (!accessToken) throw new Error('No Copilot bearer token');\n      storage.reload();\n\n      const refreshed = storage.get(COPILOT_PROVIDER_ID);\n      const enterpriseUrl = (refreshed as GitHubCopilotCredentials | undefined)?.enterpriseUrl;\n      const baseUrl = getGitHubCopilotBaseUrl(accessToken, enterpriseUrl);\n\n      const controller = new AbortController();\n      const timer = setTimeout(() => controller.abort(), CATALOG_FETCH_TIMEOUT_MS);\n      try {\n        const models = await fetchCopilotModels({\n          baseUrl,\n          bearerToken: accessToken,\n          signal: controller.signal,\n        });\n        catalogCache = { fetchedAt: Date.now(), ttl: CATALOG_TTL_MS, models };\n        return models;\n      } finally {\n        clearTimeout(timer);","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/providers/github-copilot.ts#L357-L393","documentation":"getCopilotModelCatalog fetches the live GitHub Copilot model list and requires a Copilot OAuth bearer token. It calls storage.getApiKey('github-copilot'), which refreshes the token if expired; if that returns nothing, it throws 'No Copilot bearer token'. Internally the error is caught, a hard-coded fallback model list is cached, and a warning is logged, so callers usually just get the fallback catalog.","triggerScenarios":"Calling getCopilotModelCatalog (directly or via copilotModels/models listing) when the stored 'github-copilot' credential exists and is type 'oauth' (passing the cred check), but storage.getApiKey('github-copilot') returns null/undefined — i.e. no stored API key/access token and refresh fails or no refresh token is present.","commonSituations":"User logged out of GitHub Copilot while a stale oauth credential record remains; expired refresh token so getApiKey cannot mint a new bearer; a custom AuthStorage/credentialStore injected that has the provider entry but no key material; corrupted credentials file after a version migration.","solutions":["Run the Copilot OAuth login/refresh flow (e.g. the SDK's copilot login command) to store a fresh bearer token.","Check the stored credential file for the 'github-copilot' entry and ensure it contains a valid access/refresh token, not just an empty oauth record.","Verify the injected authStorage (if passing opts.authStorage) actually contains Copilot credentials.","Ignore-and-degrade if acceptable: the library catches this and falls back to a hard-coded model list."],"exampleFix":"// before\nconst models = await getCopilotModelCatalog(); // warns and returns fallback if no token\n// after\nconst cred = authStorage.get('github-copilot');\nif (!cred || cred.type !== 'oauth' || !(await authStorage.getApiKey('github-copilot'))) {\n  await runCopilotLogin(); // refresh credentials first\n}\nconst models = await getCopilotModelCatalog();","handlingStrategy":"fallback","validationCode":"const cred = storage.get('github-copilot');\nconst token = cred?.type === 'oauth' ? await storage.getApiKey('github-copilot') : null;\nif (!token) console.warn('Copilot not authenticated; catalog will use fallback models');","typeGuard":"function hasCopilotCredential(s: CredentialStore): boolean {\n  const c = s.get('github-copilot');\n  return !!c && c.type === 'oauth';\n}","tryCatchPattern":"let models: CopilotModelEntry[];\ntry {\n  models = await getCopilotModelCatalog();\n} catch (e) {\n  models = COPILOT_FALLBACK_MODELS; // library also degrades internally\n}","preventionTips":["Check Copilot login state before listing models and prompt for login when missing.","Refresh tokens proactively before long sessions rather than relying on lazy refresh.","In CI, ensure the Copilot credentials file is provisioned or skip live catalog fetch."],"tags":["auth","oauth","github-copilot","token-refresh"],"backgroundTag":"missing-oauth-bearer-token","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}