larksuite/cli · error
Device authorization failed: %s
Error message
Device authorization failed: %s
What it means
The device-authorization endpoint responded with JSON, but the payload carries an OAuth error field (or the HTTP status is >=400). The server's error_description or error string is surfaced directly after the 'Device authorization failed:' prefix, falling back to 'Unknown error'.
Source
Thrown at internal/auth/device_flow.go:119
if err != nil {
return nil, fmt.Errorf("Device authorization failed: read body: %v", err)
}
var data map[string]interface{}
if err := json.Unmarshal(body, &data); err != nil {
return nil, fmt.Errorf("Device authorization failed: HTTP %d – response not JSON", resp.StatusCode)
}
_, hasError := data["error"]
if resp.StatusCode >= 400 || hasError {
msg := getStr(data, "error_description")
if msg == "" {
msg = getStr(data, "error")
}
if msg == "" {
msg = "Unknown error"
}
return nil, fmt.Errorf("Device authorization failed: %s", msg)
}
expiresIn := getInt(data, "expires_in", 240)
interval := getInt(data, "interval", 5)
verificationUri := getStr(data, "verification_uri")
verificationUriComplete := getStr(data, "verification_uri_complete")
if verificationUriComplete == "" {
verificationUriComplete = verificationUri
}
return &DeviceAuthResponse{
DeviceCode: getStr(data, "device_code"),
UserCode: getStr(data, "user_code"),
VerificationUri: verificationUri,
VerificationUriComplete: verificationUriComplete,
ExpiresIn: expiresIn,
Interval: interval,View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Read the embedded server message (error_description) — it names the OAuth error such as invalid_client or unauthorized_client.
- Confirm the app's client_id/credentials in the Feishu/Lark developer console.
- Enable the device authorization grant / relevant scopes for the app and get tenant admin approval if required.
- If the message is 'Unknown error', capture the raw response and the HTTP status to debug further.
Defensive patterns
Strategy: try-catch
Type guard
func isDeviceAuthRejected(err error) bool {
return err != nil && strings.HasPrefix(err.Error(), "Device authorization failed: ")
} Try / catch
resp, err := auth.RequestDeviceAuthorization(ctx, clientID, scopes)
if err != nil {
if isDeviceAuthRejected(err) {
// surface the embedded OAuth error (error_description) to the user
return fmt.Errorf("fix app config/grant type before retrying: %w", err)
}
return err
} Prevention
- Enable the device authorization grant for the app in the Feishu developer console.
- Keep client_id/app credentials current; stale deleted apps yield invalid_client.
- Obtain tenant admin approval for required scopes before running the flow.
- Surface error_description to end users instead of a generic message.
When it happens
Trigger: RequestDeviceAuthorization sees resp.StatusCode >= 400 or data["error"] present — e.g. invalid client_id, unauthorized_client, access_denied, or the app is not enabled for device flow (grant type not allowed).
Common situations: App credentials (client_id) wrong or app deleted; device-grant type not enabled in the Lark/Feishu developer console; tenant admin disabled the app or scopes; expired/misconfigured app configuration after a version change.
Related errors
- app registration failed: %s
- failed to parse response: %w
- app registration failed: HTTP %d – response not JSON
- poll request: %w
- Device authorization failed: read body: %v
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/a7520ee778851e72.
Report an issue: GitHub.