{"record":{"id":"a5e77f3e8371e671","repo":"CherryHQ/cherry-studio","slug":"feishu-app-registration-timed-out","errorCode":null,"errorMessage":"Feishu app registration timed out","messagePattern":"Feishu app registration timed out","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/main/ai/channels/adapters/feishu/FeishuAppRegistration.ts","lineNumber":137,"sourceCode":"    switch (error as PollStatus) {\n      case 'authorization_pending':\n        continue\n      case 'slow_down':\n        interval += 5000\n        continue\n      case 'access_denied':\n        throw new Error('User denied the Feishu app registration')\n      case 'expired_token':\n        throw new Error('Feishu app registration QR code expired')\n      default:\n        if (error) {\n          throw new Error(`Feishu registration poll error: ${error}`)\n        }\n        continue\n    }\n  }\n\n  throw new Error('Feishu app registration timed out')\n}\n","sourceCodeStart":119,"sourceCodeEnd":139,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/channels/adapters/feishu/FeishuAppRegistration.ts#L119-L139","documentation":"Thrown by registrationPoll() when the loop exits because Date.now() exceeded the deadline (now + expires_in*1000) without obtaining credentials and without an explicit error. This is the local timeout fallback that runs even if the server keeps returning authorization_pending.","triggerScenarios":"expiresIn seconds elapse with the poll still receiving authorization_pending; the while(Date.now() < deadline) condition becomes false and execution falls to the trailing throw.","commonSituations":"User never scanned the QR, or scanned but never approved, and the server kept returning pending until the local deadline hit.","solutions":["Restart the flow with registrationBegin to issue a fresh QR/device_code.","Confirm expiresIn was read correctly from the begin response (default 600s) and not accidentally shortened.","Improve UX so the user is reminded to scan (countdown + notification)."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Confirm expiresIn was read from the begin response and not shortened.\nconst expiresIn = (res.expires_in as number) ?? 600\nif (expiresIn < 60) throw new Error('Suspiciously short expiresIn from registration begin')","typeGuard":"function isFeishuRegistrationTimeout(e: unknown): e is Error {\n  return e instanceof Error && e.message === 'Feishu app registration timed out'\n}","tryCatchPattern":"try {\n  await registrationPoll(domain, deviceCode, opts)\n} catch (e) {\n  if (isFeishuRegistrationTimeout(e)) { notifyUser('Scan timed out'); return restartRegistrationFlow() }\n  throw e\n}","preventionTips":["Restart with registrationBegin to get a fresh device_code/QR.","Remind the user to scan with a visible countdown.","Verify expiresIn propagation from begin to poll."],"tags":["feishu","registration","timeout","device-flow","polling"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}