CherryHQ/cherry-studio · warning · Error

Feishu app registration timed out

Error message

Feishu app registration timed out

What it means

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.

Source

Thrown at src/main/ai/channels/adapters/feishu/FeishuAppRegistration.ts:137

    switch (error as PollStatus) {
      case 'authorization_pending':
        continue
      case 'slow_down':
        interval += 5000
        continue
      case 'access_denied':
        throw new Error('User denied the Feishu app registration')
      case 'expired_token':
        throw new Error('Feishu app registration QR code expired')
      default:
        if (error) {
          throw new Error(`Feishu registration poll error: ${error}`)
        }
        continue
    }
  }

  throw new Error('Feishu app registration timed out')
}

View on GitHub (pinned to 726446b54c)

Solutions

  1. Restart the flow with registrationBegin to issue a fresh QR/device_code.
  2. Confirm expiresIn was read correctly from the begin response (default 600s) and not accidentally shortened.
  3. Improve UX so the user is reminded to scan (countdown + notification).
Defensive patterns

Strategy: retry

Validate before calling

// Confirm expiresIn was read from the begin response and not shortened.
const expiresIn = (res.expires_in as number) ?? 600
if (expiresIn < 60) throw new Error('Suspiciously short expiresIn from registration begin')

Type guard

function isFeishuRegistrationTimeout(e: unknown): e is Error {
  return e instanceof Error && e.message === 'Feishu app registration timed out'
}

Try / catch

try {
  await registrationPoll(domain, deviceCode, opts)
} catch (e) {
  if (isFeishuRegistrationTimeout(e)) { notifyUser('Scan timed out'); return restartRegistrationFlow() }
  throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: User never scanned the QR, or scanned but never approved, and the server kept returning pending until the local deadline hit.

Understand the failure class

Related errors


AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12). Data as JSON: /api/errors/a5e77f3e8371e671. Report an issue: GitHub.