{"record":{"id":"931263eaf00a8355","repo":"CherryHQ/cherry-studio","slug":"failed-to-get-access-token-http-response-status","errorCode":null,"errorMessage":"Failed to get access token: HTTP ${response.status}","messagePattern":"Failed to get access token: HTTP (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ai/channels/adapters/qq/QqAdapter.ts","lineNumber":171,"sourceCode":"  }\n\n  private async getAccessToken(): Promise<string> {\n    // Check cache\n    if (this.tokenCache && Date.now() < this.tokenCache.expiresAt - 60000) {\n      return this.tokenCache.accessToken\n    }\n\n    const response = await net.fetch('https://bots.qq.com/app/getAppAccessToken', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify({\n        appId: this.appId,\n        clientSecret: this.clientSecret\n      })\n    })\n\n    if (!response.ok) {\n      throw new Error(`Failed to get access token: HTTP ${response.status}`)\n    }\n\n    const data = (await response.json()) as { access_token?: string; expires_in?: number }\n    if (!data.access_token || !data.expires_in) {\n      const errorText = JSON.stringify(data)\n      throw new Error(`Invalid token response from QQ API: ${errorText}`)\n    }\n\n    this.tokenCache = {\n      accessToken: data.access_token,\n      expiresAt: Date.now() + data.expires_in * 1000\n    }\n\n    return data.access_token\n  }\n\n  private async apiRequest(\n    endpoint: string,","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/channels/adapters/qq/QqAdapter.ts#L153-L189","documentation":"Thrown when the QQ AppAccessToken endpoint (https://bots.qq.com/app/getAppAccessToken) returns a non-2xx status. The message embeds response.status only; the body is not read. This token is mandatory for subsequent QQ API calls (Authorization: QQBot <token>).","triggerScenarios":"net.fetch POST to getAppAccessToken with {appId, clientSecret} returns response.ok === false; the guard throws HTTP <status> before parsing JSON.","commonSituations":"Wrong appId/clientSecret (QQ returns 4xx), QQ service degradation (5xx), network/proxy returning an error page, or rate limiting on the token endpoint.","solutions":["Confirm appId/clientSecret are correct and match a QQ bot in the q.qq.com console.","For 5xx or rate-limit status, back off and retry the token request.","Read the response body for QQ's error detail to disambiguate 401 (bad creds) vs 429 (rate limit).","Ensure the host can reach bots.qq.com without TLS interception."],"exampleFix":"// before\nif (!response.ok) {\n  throw new Error(`Failed to get access token: HTTP ${response.status}`)\n}\n\n// after — include body for diagnosis and retry on transient 5xx\nif (!response.ok) {\n  const detail = await response.text().catch(() => '')\n  if (response.status >= 500) {\n    await new Promise((r) => setTimeout(r, 1000))\n    return this.fetchAccessToken() // bounded retry\n  }\n  throw new Error(`Failed to get access token: HTTP ${response.status} - ${detail}`)\n}","handlingStrategy":"retry","validationCode":"// Pre-flight: token endpoint reachable and credentials present.\nfunction qqCanFetchToken(appId?: string, clientSecret?: string): boolean {\n  return Boolean(appId?.trim() && clientSecret?.trim())\n}","typeGuard":"function isQqTokenHttpError(e: unknown): e is Error {\n  return e instanceof Error && /^Failed to get access token: HTTP \\d+$/.test(e.message)\n}","tryCatchPattern":"try {\n  await qq.connect()\n} catch (e) {\n  if (isQqTokenHttpError(e)) {\n    const status = Number(/HTTP (\\d+)/.exec(e.message)?.[1] ?? 0)\n    if (status >= 500) return retryConnect()\n    notifyUser('QQ credentials rejected or token endpoint down')\n    return\n  }\n  throw e\n}","preventionTips":["Confirm appId/clientSecret from the q.qq.com console.","Back off on 5xx/429; surface 4xx as a credentials problem.","Ensure network reachability to bots.qq.com without TLS interception."],"tags":["qq","auth","http","token","network"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}