{"record":{"id":"c2a8e6838324f3f0","repo":"can1357/oh-my-pi","slug":"too-many-pending-authorization-requests-please-tr","errorCode":null,"errorMessage":"Too many pending authorization requests. Please try again later.","messagePattern":"Too many pending authorization requests\\. Please try again later\\.","errorType":"exception","errorClass":"AIError.OAuthError","httpStatus":429,"severity":"warning","filePath":"packages/ai/src/registry/kilo.ts","lineNumber":29,"sourceCode":"\tverificationUrl?: string;\n\texpiresIn?: number;\n}\n\ninterface KiloDeviceAuthPollResponse {\n\tstatus?: string;\n\ttoken?: string;\n}\n\nexport async function loginKilo(callbacks: OAuthController): Promise<OAuthCredentials> {\n\tconst fetchImpl = callbacks.fetch ?? fetch;\n\tconst initiateResponse = await fetchImpl(`${KILO_DEVICE_AUTH_BASE_URL}/codes`, {\n\t\tmethod: \"POST\",\n\t\theaders: { \"Content-Type\": \"application/json\" },\n\t});\n\n\tif (!initiateResponse.ok) {\n\t\tif (initiateResponse.status === 429) {\n\t\t\tthrow new AIError.OAuthError(\"Too many pending authorization requests. Please try again later.\", {\n\t\t\t\tkind: \"polling\",\n\t\t\t\tprovider: \"kilo\",\n\t\t\t\tstatus: initiateResponse.status,\n\t\t\t});\n\t\t}\n\t\tthrow new AIError.OAuthError(`Failed to initiate device authorization: ${initiateResponse.status}`, {\n\t\t\tkind: \"device-auth\",\n\t\t\tprovider: \"kilo\",\n\t\t\tstatus: initiateResponse.status,\n\t\t});\n\t}\n\n\tconst initiateData = (await initiateResponse.json()) as KiloDeviceAuthCodeResponse;\n\tconst userCode = initiateData.code;\n\tconst verificationUrl = initiateData.verificationUrl;\n\tconst expiresInSeconds = initiateData.expiresIn;\n\tif (!userCode || !verificationUrl || typeof expiresInSeconds !== \"number\" || expiresInSeconds <= 0) {\n\t\tthrow new AIError.OAuthError(\"Kilo device authorization response missing required fields\", {","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/ai/src/registry/kilo.ts#L11-L47","documentation":"Kilo's device-authorization login first POSTs to initiate a device code. When the server responds with HTTP 429 (rate limited / too many in-flight authorization requests), loginKilo throws this OAuthError with kind \"polling\" and the status attached. It signals the provider is refusing new device-auth sessions temporarily, not that your input is wrong.","triggerScenarios":"Calling loginKilo (device flow initiation) when the Kilo authorization server returns status 429 for the initiation POST — i.e. the account/IP has too many pending device authorization codes.","commonSituations":"Repeated login attempts in a short window; automated scripts retrying login in a loop; shared IP (CI farm, corporate NAT) exhausting the provider's pending-code quota; abandoned device codes never expiring client-side.","solutions":["Wait several minutes before retrying so pending authorization requests expire server-side.","Stop any loops/scripts that repeatedly call login on Kilo and retry once with backoff.","Reuse an existing valid session/token instead of initiating a new device flow.","If it persists, contact Kilo support or check service status — the pending-code quota may need clearing server-side."],"exampleFix":"// before\nfor (let i = 0; i < 10; i++) await loginKilo(callbacks); // hammers initiation endpoint -> 429\n// after\nconst { promise, resolve } = Promise.withResolvers();\nawait Bun.sleep(5000);\nawait loginKilo(callbacks); // single attempt after backoff","handlingStrategy":"retry","validationCode":"// throttle device-logins client-side to stay under the pending-code quota\nlet lastKiloLogin = 0;\nasync function loginKiloThrottled(cb: OAuthCallbacks) {\n  const since = Date.now() - lastKiloLogin;\n  if (since < 60_000) await Bun.sleep(60_000 - since);\n  lastKiloLogin = Date.now();\n  return loginKilo(cb);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await loginKilo(callbacks);\n} catch (err) {\n  if (err instanceof AIError.OAuthError && err.message.includes(\"Too many pending\")) {\n    await Bun.sleep(120_000);\n    return loginKilo(callbacks); // retry after backoff\n  }\n  throw err;\n}","preventionTips":["Don't retry login in tight loops; use exponential backoff.","Clean up stale sessions so fewer device codes are pending.","Serialize logins in CI rather than running them concurrently.","Treat 429 as temporary — wait minutes, not seconds."],"tags":["oauth","rate-limit","kilo","device-flow","http-429"],"backgroundTag":"rate-limit-exceeded","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}