{"record":{"id":"9758a24a4ef82392","repo":"router-for-me/CLIProxyAPI","slug":"kimi-failed-to-read-device-code-response-w","errorCode":null,"errorMessage":"kimi: failed to read device code response: %w","messagePattern":"kimi: failed to read device code response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/auth/kimi/kimi.go","lineNumber":207,"sourceCode":"\treq.Header.Set(\"Content-Type\", \"application/x-www-form-urlencoded\")\n\treq.Header.Set(\"Accept\", \"application/json\")\n\tfor k, v := range c.commonHeaders() {\n\t\treq.Header.Set(k, v)\n\t}\n\n\tresp, err := c.httpClient.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"kimi: device code request failed: %w\", err)\n\t}\n\tdefer func() {\n\t\tif errClose := resp.Body.Close(); errClose != nil {\n\t\t\tlog.Errorf(\"kimi device code: close body error: %v\", errClose)\n\t\t}\n\t}()\n\n\tbodyBytes, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"kimi: failed to read device code response: %w\", err)\n\t}\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"kimi: device code request failed with status %d: %s\", resp.StatusCode, string(bodyBytes))\n\t}\n\n\tvar deviceCode DeviceCodeResponse\n\tif err = json.Unmarshal(bodyBytes, &deviceCode); err != nil {\n\t\treturn nil, fmt.Errorf(\"kimi: failed to parse device code response: %w\", err)\n\t}\n\n\treturn &deviceCode, nil\n}\n\n// PollForToken polls the token endpoint until the user authorizes or the device code expires.\nfunc (c *DeviceFlowClient) PollForToken(ctx context.Context, deviceCode *DeviceCodeResponse) (*KimiTokenData, error) {\n\tif deviceCode == nil {\n\t\treturn nil, fmt.Errorf(\"kimi: device code is nil\")","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/auth/kimi/kimi.go#L189-L225","documentation":"The HTTP POST to Kimi's device authorization endpoint (https://auth.kimi.com/api/oauth/device_authorization) succeeded at the transport level, but reading the response body with io.ReadAll failed. This means the connection was interrupted between receiving response headers and receiving the full body. The device code was never obtained, so the device flow cannot proceed.","triggerScenarios":"Connection reset or TLS renegotiation mid-body while auth.kimi.com streams the device code JSON; an intercepting proxy that closes the stream early; response with Content-Length larger than what the server actually sends; very slow network causing the client reader to abort.","commonSituations":"Corporate proxies/MITM proxies truncating responses, flaky mobile or containerized networks, transient Moonshot-side connection resets, running in CI with restricted egress that allows headers but drops body.","solutions":["Retry StartDeviceFlow once — this is a transient transport failure and a new request gets a fresh connection","Check whether an HTTP(S) proxy (HTTP_PROXY/HTTPS_PROXY env vars) is interfering and bypass or configure it for auth.kimi.com","Verify basic connectivity: curl -i -X POST https://auth.kimi.com/api/oauth/device_authorization and confirm the body arrives fully","If it persists, inspect httpClient timeout configuration in NewDeviceFlowClient — a very short client timeout can abort mid-body reads"],"exampleFix":"// before\ndeviceCode, err := k.StartDeviceFlow(ctx)\nif err != nil {\n    return err // fails outright on transient body read error\n}\n\n// after\ndeviceCode, err := k.StartDeviceFlow(ctx)\nif err != nil {\n    if isTransientNetErr(err) { // net.Error, io.ErrUnexpectedEOF, connection reset\n        time.Sleep(2 * time.Second)\n        deviceCode, err = k.StartDeviceFlow(ctx)\n    }\n    if err != nil {\n        return err\n    }\n}","handlingStrategy":"retry","validationCode":"// Verify the auth host is reachable and proxy env is sane before starting the flow\nif _, err := net.LookupHost(\"auth.kimi.com\"); err != nil {\n    return fmt.Errorf(\"cannot resolve auth.kimi.com: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"failed to read device code response\") {\n    time.Sleep(2 * time.Second)\n    deviceCode, err = k.StartDeviceFlow(ctx)\n}","preventionTips":["Exclude auth.kimi.com from MITM/intercepting proxies","Ensure stable egress before starting interactive login","Treat any single transport failure on device code as retryable"],"tags":["kimi","oauth","device-flow","network","http"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}