CherryHQ/cherry-studio · error · Error

Feishu registration poll error: ${error}

Error message

Feishu registration poll error: ${error}

What it means

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.

Source

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

        openId: userInfo?.open_id
      }
    }

    // Handle error states
    const error = (res.error as string) ?? ''
    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. Read the embedded error string and map it to the OAuth/Device-Flow spec (RFC 8628) for semantics.
  2. For transient codes (temporarily_unavailable), back off and continue polling; for fatal codes, restart with registrationBegin.
  3. If Feishu formalized a new code, add an explicit case to the switch.
Defensive patterns

Strategy: try-catch

Validate before calling

// No pre-call validation: unknown errors are server-driven.
// Defense is classification after the fact.

Type guard

function isFeishuPollError(e: unknown): e is Error {
  return e instanceof Error && e.message.startsWith('Feishu registration poll error:')
}

Try / catch

try {
  await registrationPoll(domain, deviceCode, opts)
} catch (e) {
  if (isFeishuPollError(e)) {
    const code = e.message.split(':').pop()?.trim() ?? ''
    if (/temporarily_unavailable|invalid_grant/.test(code)) return restartRegistrationFlow()
  }
  throw e
}

Prevention

When it happens

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

Common situations: 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.

Related errors


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