{"record":{"id":"1b5305ed071856db","repo":"larksuite/cli","slug":"poll-read-error-w","errorCode":null,"errorMessage":"poll read error: %w","messagePattern":"poll read error: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/auth/app_registration.go","lineNumber":203,"sourceCode":"\tform.Set(\"action\", \"poll\")\n\tform.Set(\"device_code\", deviceCode)\n\n\treq, err := http.NewRequestWithContext(ctx, \"POST\", appRegistrationEndpoint(brand), strings.NewReader(form.Encode()))\n\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","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/auth/app_registration.go#L185-L221","documentation":"Thrown by pollOnce at internal/auth/app_registration.go:203 when io.ReadAll fails reading the poll response body. Like other poll failures, RegisterAppWithDiscovery treats this as transient: it logs a warning, backs off the interval, and keeps polling until the registration deadline.","triggerScenarios":"The poll response stream breaks mid-read: server/proxy closes the connection early, chunked encoding truncated, or the context deadline cancels the read partway through the body.","commonSituations":"Unstable networks during long device-flow waits; load balancers with short idle timeouts killing slow poll responses; VPN drops mid-registration.","solutions":["Allow the CLI to continue — it retries polling automatically with backoff.","If registration ultimately times out, restart the flow on a stabler network.","Investigate proxy/LB idle-timeout settings if this recurs every poll cycle.","Disable VPN or switch networks if connectivity is intermittent."],"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 read error:\") {\n        // transient: back off and retry the poll\n        time.Sleep(interval * time.Second)\n        return pollOnce(ctx, client, brand, deviceCode)\n    }\n    return nil, err\n}","preventionTips":["Use stable networks for long-running device flows.","Raise proxy/load-balancer idle timeouts above the poll interval.","Avoid VPN drops mid-registration."],"tags":["network","io","polling","device-flow"],"backgroundTag":"http-body-read-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"}