{"record":{"id":"8d34bbdb0cb81985","repo":"can1357/oh-my-pi","slug":"authorization-was-denied","errorCode":null,"errorMessage":"Authorization was denied","messagePattern":"Authorization was denied","errorType":"exception","errorClass":"AIError.OAuthError","httpStatus":403,"severity":"error","filePath":"packages/ai/src/registry/kilo.ts","lineNumber":70,"sourceCode":"\n\tcallbacks.onAuth?.({\n\t\turl: verificationUrl,\n\t\tinstructions: `Enter code: ${userCode}`,\n\t});\n\n\tconst deadline = Date.now() + expiresInSeconds * 1000;\n\twhile (Date.now() < deadline) {\n\t\tif (callbacks.signal?.aborted) {\n\t\t\tthrow new AIError.LoginCancelledError();\n\t\t}\n\n\t\tconst pollResponse = await fetchImpl(`${KILO_DEVICE_AUTH_BASE_URL}/codes/${encodeURIComponent(userCode)}`);\n\t\tif (pollResponse.status === 202) {\n\t\t\tawait Bun.sleep(POLL_INTERVAL_MS);\n\t\t\tcontinue;\n\t\t}\n\t\tif (pollResponse.status === 403) {\n\t\t\tthrow new AIError.OAuthError(\"Authorization was denied\", { kind: \"device-auth\", provider: \"kilo\" });\n\t\t}\n\t\tif (pollResponse.status === 410) {\n\t\t\tthrow new AIError.OAuthError(\"Authorization code expired. Please try again.\", {\n\t\t\t\tkind: \"device-auth\",\n\t\t\t\tprovider: \"kilo\",\n\t\t\t});\n\t\t}\n\t\tif (!pollResponse.ok) {\n\t\t\tthrow new AIError.OAuthError(`Failed to poll device authorization: ${pollResponse.status}`, {\n\t\t\t\tkind: \"polling\",\n\t\t\t\tprovider: \"kilo\",\n\t\t\t\tstatus: pollResponse.status,\n\t\t\t});\n\t\t}\n\n\t\tconst pollData = (await pollResponse.json()) as KiloDeviceAuthPollResponse;\n\t\tif (pollData.status === \"approved\" && pollData.token) {\n\t\t\treturn {","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/ai/src/registry/kilo.ts#L52-L88","documentation":"While polling Kilo's device-code endpoint for approval, an HTTP 403 means the authorization was explicitly denied (or the code was rejected). loginKilo converts this into an OAuthError with kind \"device-auth\" and this fixed message. Contrast with 202 (still pending) and 410 (expired).","triggerScenarios":"The poll GET `${KILO_DEVICE_AUTH_BASE_URL}/codes/<userCode>` returns status 403 — the user clicked 'Deny' on the verification page, or the server rejects the code/identity at approval time.","commonSituations":"User denies the request in the browser by mistake or deliberately; the verification page session doesn't match the requesting account; security software or an admin policy blocks approval.","solutions":["Restart the login flow (call loginKilo again) to generate a fresh device code and approve it this time.","Confirm you open the exact verificationUrl shown and approve with the intended account.","Check for org/security policies or browser extensions blocking the approval action.","If denials are unexpected, verify the device code was entered correctly and wasn't for someone else's request."],"exampleFix":"// before\nawait loginKilo(callbacks); // user clicks Deny -> unhandled OAuthError\n// after\ntry {\n  await loginKilo(callbacks);\n} catch (err) {\n  if (AIError.OAuthError.is(err) && err.message === \"Authorization was denied\") {\n    return promptRetry(\"Authorization denied — start login again to approve.\");\n  }\n  throw err;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await loginKilo(callbacks);\n} catch (err) {\n  if (err instanceof AIError.OAuthError && err.message === \"Authorization was denied\") {\n    console.error(\"Login denied on the verification page — run login again and choose Approve.\");\n    return null;\n  }\n  throw err;\n}","preventionTips":["Instruct users to click Approve (not Deny) on the verification page.","Have users verify the user code matches before approving.","Restart the flow with a fresh code after any denial — codes are single-use for approval decisions.","Check org policies/browser extensions if approvals are unexpectedly rejected."],"tags":["oauth","kilo","device-flow","authorization-denied","http-403"],"backgroundTag":"authorization-denied","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}