{"record":{"id":"bd0a5f37ad323349","repo":"paperclipai/paperclip","slug":"invalid-login","errorCode":null,"errorMessage":"Invalid login","messagePattern":"Invalid login","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/services/local-ai-credentials.ts","lineNumber":54,"sourceCode":"      if (!token) throw new Error(\"Missing login\");\n      await fetchClaudeQuota(token);\n      return token;\n    }\n    if (provider === \"openai\") {\n      const auth = await readCodexAuthInfo(loginHome);\n      if (!auth?.accessToken || !auth.refreshToken || !auth.idToken) throw new Error(\"Missing login\");\n      await fetchCodexQuota(auth.accessToken, auth.accountId);\n      return JSON.stringify({ tokens: { access_token: auth.accessToken, refresh_token: auth.refreshToken, id_token: auth.idToken, account_id: auth.accountId }, last_refresh: auth.lastRefresh });\n    }\n    const raw = await fs.readFile(path.join(loginHome!, \"auth.json\"), \"utf8\");\n    const payload = parseGrokAuthPayload(JSON.parse(raw));\n    if (!payload || !hasUsableGrokAuthValue(payload.value)) throw new Error(\"Missing login\");\n    const response = await fetch(\"https://api.x.ai/v1/models\", {\n      headers: { Authorization: `Bearer ${payload.value.key}` },\n      redirect: \"error\", signal: AbortSignal.timeout(15000),\n    });\n    await response.body?.cancel();\n    if (!response.ok) throw new Error(\"Invalid login\");\n    return raw;\n  } catch {\n    // Provider/CLI errors may contain credential material; never return them.\n    throw unprocessable(provider === \"anthropic\" && !loginHome\n      ? \"Could not verify the local subscription. Run claude auth login in a terminal on the machine running Paperclip, then try Connect again.\"\n      : \"Could not verify the local subscription. Run the sign-in command shown for this connection, finish signing in, then try Connect again.\");\n  }\n}\n","sourceCodeStart":36,"sourceCodeEnd":63,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/local-ai-credentials.ts#L36-L63","documentation":"After loading a grok auth payload, the service probes https://api.x.ai/v1/models with the stored bearer key (redirects forbidden, 15s timeout). A non-ok response throws 'Invalid login' — the credential exists but x.ai rejected it. The outer catch converts all provider errors into an unprocessable-entity message so credential material is never leaked in error text.","triggerScenarios":"Stored xAI API key revoked or expired; key lacks access to /v1/models; x.ai returns 401/403/5xx; network/timeout treated by the catch path (surfaced as the generic unprocessable message rather than this throw, but the same Connect flow).","commonSituations":"Rotated the API key in the xAI console without re-running sign-in; team key deactivated; org suspended; key created with restricted scopes.","solutions":["Re-run the provider sign-in command to store a fresh xAI key, then retry Connect","Verify the key is active and valid at console.x.ai; generate a new one if revoked","Confirm the key has permission to call /v1/models (no org/scope restrictions)","Check connectivity/egress to api.x.ai from the server if status is 5xx"],"exampleFix":"// before\n# key revoked in xAI console; auth.json still holds old key\n// after\n# generate new key at console.x.ai, re-run sign-in command, retry Connect","handlingStrategy":"retry","validationCode":"// pre-check the key yourself before connecting\nconst res = await fetch(\"https://api.x.ai/v1/models\", {\n  headers: { Authorization: `Bearer ${key}` }, signal: AbortSignal.timeout(15000),\n});\nif (!res.ok) console.error(`xAI key rejected: HTTP ${res.status} — rotate the key and re-run sign-in`);","typeGuard":null,"tryCatchPattern":"try {\n  await readVerifiedLocalAiCredential({ provider: \"grok\", loginHome });\n} catch (e) {\n  if (/Could not verify the local subscription/.test(String(e?.message))) {\n    // invalid or unverifiable key: guide the user to regenerate and re-sign-in\n    showSetupHint(\"Key rejected by api.x.ai; generate a new key and re-run sign-in\");\n  } else throw e;\n}","preventionTips":["Rotate keys in the xAI console and immediately re-run the sign-in command","Only grant keys access to /v1/models (or the scopes your integration needs)","Retry once on 5xx with backoff before treating the login as invalid","Monitor xAI org/key status to catch revocations before Connect attempts"],"tags":["auth","api","xai"],"backgroundTag":"upstream-api-error","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}