{"record":{"id":"4cb088293ebd47fb","repo":"larksuite/cli","slug":"poll-parse-error-w","errorCode":null,"errorMessage":"poll parse error: %w","messagePattern":"poll parse error: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/auth/app_registration.go","lineNumber":207,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"poll request: %w\", err)\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/x-www-form-urlencoded\")\n\n\tresp, err := httpClient.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"poll network error: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\tlogHTTPResponse(resp)\n\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"poll read error: %w\", err)\n\t}\n\tvar data map[string]interface{}\n\tif err := json.Unmarshal(body, &data); err != nil {\n\t\treturn nil, fmt.Errorf(\"poll parse error: %w\", err)\n\t}\n\treturn data, nil\n}\n\n// RegisterAppWithDiscovery polls for credentials, mirroring the official SDK\n// flow: the first poll and the (at most one) cross-brand switch are immediate,\n// non-error responses without complete credentials keep polling, and one\n// deadline from the begin expiry bounds all waits and in-flight requests.\n// The returned brand is the one the credentials were issued on.\nfunc RegisterAppWithDiscovery(ctx context.Context, httpClient *http.Client, resp *AppRegistrationResponse, errOut io.Writer) (*AppRegistrationResult, core.LarkBrand, error) {\n\tif errOut == nil {\n\t\terrOut = io.Discard\n\t}\n\n\t// Interval and expiry arrive normalized from begin-response parsing\n\t// (normalizedInterval floors them there); the loop trusts them as-is.\n\tinterval := resp.Interval\n\tctx, cancel := context.WithDeadline(ctx,","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/auth/app_registration.go#L189-L225","documentation":"Thrown by pollOnce at internal/auth/app_registration.go:207 when json.Unmarshal cannot parse the poll response body as a JSON object. RegisterAppWithDiscovery logs it as a warning, increases the poll interval, and continues, so a persistent parse failure ends as a registration timeout rather than this error.","triggerScenarios":"The poll endpoint returns non-JSON: HTML error/challenge page, empty body from a 5xx gateway response, plaintext proxy block page, or a protocol change returning a different content type.","commonSituations":"Captive portal or WAF interstitial appearing mid-flow; regional endpoint outage returning HTML 502 pages; middleboxes rewriting responses between the successful begin call and later polls.","solutions":["Check the CLI log lines ('[WARN] app-registration: poll parse error: ...') and inspect the poll endpoint with curl from the same machine.","Fix captive-portal/proxy interference or switch networks.","If the server outage persists past the device-code expiry, restart registration once the service recovers.","Report a protocol regression to maintainers if a CLI/server version mismatch is suspected (update the CLI first)."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"data, err := pollOnce(ctx, client, brand, deviceCode)\nif err != nil {\n    if strings.Contains(err.Error(), \"poll parse error:\") {\n        // logged by the loop; poll again after backoff, escalate if persistent\n    }\n}\n// The built-in loop already retries; detect ultimate failure via ErrRegistrationTimedOut.","preventionTips":["Exclude accounts hosts from captive portals and WAF challenges.","Monitor service status for the regional accounts endpoint.","Keep TLS-inspection appliances from rewriting response bodies."],"tags":["json","polling","device-flow","network"],"backgroundTag":"non-json-response","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"}