{"record":{"id":"a7520ee778851e72","repo":"larksuite/cli","slug":"device-authorization-failed-s","errorCode":null,"errorMessage":"Device authorization failed: %s","messagePattern":"Device authorization failed: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/auth/device_flow.go","lineNumber":119,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"Device authorization failed: read body: %v\", err)\n\t}\n\n\tvar data map[string]interface{}\n\tif err := json.Unmarshal(body, &data); err != nil {\n\t\treturn nil, fmt.Errorf(\"Device authorization failed: HTTP %d – response not JSON\", resp.StatusCode)\n\t}\n\n\t_, hasError := data[\"error\"]\n\tif resp.StatusCode >= 400 || hasError {\n\t\tmsg := getStr(data, \"error_description\")\n\t\tif msg == \"\" {\n\t\t\tmsg = getStr(data, \"error\")\n\t\t}\n\t\tif msg == \"\" {\n\t\t\tmsg = \"Unknown error\"\n\t\t}\n\t\treturn nil, fmt.Errorf(\"Device authorization failed: %s\", msg)\n\t}\n\n\texpiresIn := getInt(data, \"expires_in\", 240)\n\tinterval := getInt(data, \"interval\", 5)\n\n\tverificationUri := getStr(data, \"verification_uri\")\n\tverificationUriComplete := getStr(data, \"verification_uri_complete\")\n\tif verificationUriComplete == \"\" {\n\t\tverificationUriComplete = verificationUri\n\t}\n\n\treturn &DeviceAuthResponse{\n\t\tDeviceCode:              getStr(data, \"device_code\"),\n\t\tUserCode:                getStr(data, \"user_code\"),\n\t\tVerificationUri:         verificationUri,\n\t\tVerificationUriComplete: verificationUriComplete,\n\t\tExpiresIn:               expiresIn,\n\t\tInterval:                interval,","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/auth/device_flow.go#L101-L137","documentation":"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'.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isDeviceAuthRejected(err error) bool {\n    return err != nil && strings.HasPrefix(err.Error(), \"Device authorization failed: \")\n}","tryCatchPattern":"resp, err := auth.RequestDeviceAuthorization(ctx, clientID, scopes)\nif err != nil {\n    if isDeviceAuthRejected(err) {\n        // surface the embedded OAuth error (error_description) to the user\n        return fmt.Errorf(\"fix app config/grant type before retrying: %w\", err)\n    }\n    return err\n}","preventionTips":["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."],"tags":["oauth","device-flow","auth","http"],"backgroundTag":"oauth-authorization-failed","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}