{"record":{"id":"5bfa3e027e4c68b6","repo":"chenhg5/cc-connect","slug":"read-response-w","errorCode":null,"errorMessage":"read response: %w","messagePattern":"read response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/speech.go","lineNumber":92,"sourceCode":"\twriter.Close()\n\n\turl := w.BaseURL + \"/audio/transcriptions\"\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, &buf)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"create request: %w\", err)\n\t}\n\treq.Header.Set(\"Authorization\", \"Bearer \"+w.APIKey)\n\treq.Header.Set(\"Content-Type\", writer.FormDataContentType())\n\n\tresp, err := w.Client.Do(req)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"whisper request: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"read response: %w\", err)\n\t}\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn \"\", fmt.Errorf(\"whisper API %d: %s\", resp.StatusCode, string(body))\n\t}\n\n\t// response_format=text returns plain text; try to handle JSON fallback\n\ttext := strings.TrimSpace(string(body))\n\tif strings.HasPrefix(text, \"{\") {\n\t\tvar jr struct {\n\t\t\tText string `json:\"text\"`\n\t\t}\n\t\tif json.Unmarshal(body, &jr) == nil {\n\t\t\ttext = jr.Text\n\t\t}\n\t}\n\treturn text, nil\n}","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/speech.go#L74-L110","documentation":"io.ReadAll failed while draining the Whisper API response body. This happens if the connection is reset mid-response, the server closes the connection prematurely, or the context is cancelled/timed out during body read.","triggerScenarios":"Transcribe receives a response but the TCP connection breaks before the full body is read — server restart, load-balancer timeout, context cancellation, or network interruption during read.","commonSituations":"Unstable network or VPN drops mid-upload/response; ASR proxy with aggressive idle timeouts; large response truncated by an intermediary.","solutions":["Retry the transcription — transient connection resets usually succeed on retry","Check intermediary (proxy/LB) timeouts and raise them for long ASR responses","Inspect the wrapped error for 'connection reset by peer' vs 'context canceled' to distinguish network vs cancellation"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"text, err := stt.Transcribe(ctx, audio, format, lang)\nif err != nil && strings.Contains(err.Error(), \"read response\") {\n    if !errors.Is(err, context.Canceled) {\n        text, err = stt.Transcribe(ctx, audio, format, lang) // one retry\n    }\n}","preventionTips":["Raise proxy/load-balancer idle timeouts for long ASR requests","Avoid cancelling the context while a transcription response is in flight","Prefer stable network paths for media-heavy traffic"],"tags":["network","http","io"],"backgroundTag":"network-request-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}