{"record":{"id":"689dfff29b27ef7a","repo":"mattermost-community/focalboard","slug":"error-when-parsing-response-with-code-d-w","errorCode":null,"errorMessage":"error when parsing response with code %d: %w","messagePattern":"error when parsing response with code (.+?): %w","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/client/client.go","lineNumber":148,"sourceCode":"\n\tif c.Token != \"\" {\n\t\trq.Header.Set(\"Authorization\", \"Bearer \"+c.Token)\n\t}\n\n\trp, err := c.HTTPClient.Do(rq)\n\tif err != nil || rp == nil {\n\t\treturn nil, err\n\t}\n\n\tif rp.StatusCode == http.StatusNotModified {\n\t\treturn rp, nil\n\t}\n\n\tif rp.StatusCode >= http.StatusMultipleChoices {\n\t\tdefer closeBody(rp)\n\t\tb, err := io.ReadAll(rp.Body)\n\t\tif err != nil {\n\t\t\treturn rp, fmt.Errorf(\"error when parsing response with code %d: %w\", rp.StatusCode, err)\n\t\t}\n\t\treturn rp, RequestReaderError{b}\n\t}\n\n\treturn rp, nil\n}\n\nfunc (c *Client) GetTeamRoute(teamID string) string {\n\treturn fmt.Sprintf(\"%s/%s\", c.GetTeamsRoute(), teamID)\n}\n\nfunc (c *Client) GetTeamsRoute() string {\n\treturn \"/teams\"\n}\n\nfunc (c *Client) GetBlockRoute(boardID, blockID string) string {\n\treturn fmt.Sprintf(\"%s/%s\", c.GetBlocksRoute(boardID), blockID)\n}","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/mattermost-community/focalboard/blob/a84bbb65e32edf972856b329417096ac413518e9/server/client/client.go#L130-L166","documentation":"doAPIRequestReader returns this error when reading the body of a non-2xx HTTP response fails with an I/O error while constructing a RequestReaderError. The %d is the HTTP status code and %w preserves the underlying read error. Note the response (*http.Response) is still returned alongside the error, so status code details are available to the caller.","triggerScenarios":"Any API call routed through DoAPIRequest, TeamUploadFile, or ImportArchive that receives a status >= 300, and whose error-response body cannot be read — typically the server closed the connection mid-response, chunked encoding is truncated, or a proxy terminated the body stream.","commonSituations":"Unstable networks or timeouts between client and server; reverse proxies (nginx) cutting off error responses; server crashing while generating an error response; uploading large files where the connection drops before the error body completes.","solutions":["Retry the request; the failure is typically transient connection-level","Check network path/proxy timeouts and keep-alive settings between client and server","Inspect the returned *http.Response (rp.StatusCode) even when err != nil to learn the status","Verify server-side logs for why the error response was truncated"],"exampleFix":"// before\nrp, err := client.DoAPIRequest(ctx, \"GET\", url, nil, nil)\nif err != nil {\n\treturn err\n}\n// after\nrp, err := client.DoAPIRequest(ctx, \"GET\", url, nil, nil)\nif err != nil {\n\tif rp != nil && rp.StatusCode >= 300 {\n\t\treturn fmt.Errorf(\"API returned %d: %w\", rp.StatusCode, err)\n\t}\n\treturn err\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"rp, err := client.DoAPIRequest(ctx, method, url, header, body)\nif err != nil {\n\tif rp != nil {\n\t\t// response still available; inspect rp.StatusCode\n\t\tif isTransientStatus(rp.StatusCode) {\n\t\t\treturn retryRequest(ctx, method, url, header, body)\n\t\t}\n\t}\n\treturn err\n}","preventionTips":["Set generous client timeouts for large uploads/imports (TeamUploadFile, ImportArchive)","Avoid aggressive proxy idle timeouts between client and server","Always check rp.StatusCode even when err != nil — the response is returned alongside the error","Retry idempotent requests on transient body-read failures"],"tags":["go","http-client","network","io"],"backgroundTag":"http-response-body-read-failed","analyzedSha":"a84bbb65e32edf972856b329417096ac413518e9","analyzedAt":"2026-08-30T09:22:20.720Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}