{"record":{"id":"71a7cd4f74235d8a","repo":"CherryHQ/cherry-studio","slug":"feishu-registration-poll-error-error","errorCode":null,"errorMessage":"Feishu registration poll error: ${error}","messagePattern":"Feishu registration poll error: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ai/channels/adapters/feishu/FeishuAppRegistration.ts","lineNumber":131,"sourceCode":"        openId: userInfo?.open_id\n      }\n    }\n\n    // Handle error states\n    const error = (res.error as string) ?? ''\n    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":113,"sourceCodeEnd":139,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/channels/adapters/feishu/FeishuAppRegistration.ts#L113-L139","documentation":"Catch-all for any non-empty error field returned by the registration poll that is not one of the known cases (authorization_pending, slow_down, access_denied, expired_token). The raw error string is embedded so the unknown state is observable.","triggerScenarios":"registrationPoll receives a response with an error value outside the handled switch cases (and not empty), e.g. a new OAuth error code Feishu introduced.","commonSituations":"Feishu added a new device-flow error code (e.g. 'invalid_grant', 'temporarily_unavailable'), the device_code was reused, or a server-side error string surfaced.","solutions":["Read the embedded error string and map it to the OAuth/Device-Flow spec (RFC 8628) for semantics.","For transient codes (temporarily_unavailable), back off and continue polling; for fatal codes, restart with registrationBegin.","If Feishu formalized a new code, add an explicit case to the switch."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// No pre-call validation: unknown errors are server-driven.\n// Defense is classification after the fact.","typeGuard":"function isFeishuPollError(e: unknown): e is Error {\n  return e instanceof Error && e.message.startsWith('Feishu registration poll error:')\n}","tryCatchPattern":"try {\n  await registrationPoll(domain, deviceCode, opts)\n} catch (e) {\n  if (isFeishuPollError(e)) {\n    const code = e.message.split(':').pop()?.trim() ?? ''\n    if (/temporarily_unavailable|invalid_grant/.test(code)) return restartRegistrationFlow()\n  }\n  throw e\n}","preventionTips":["Map the embedded error string to RFC 8628 device-flow semantics before deciding retry vs restart.","Add explicit switch cases when Feishu formalizes new error codes.","Log the unknown code so new failure modes are observable."],"tags":["feishu","registration","oauth","unknown-error","device-flow"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}