{"record":{"id":"45b079751870a6fc","repo":"hyperledger/fabric","slug":"error-reading-multipart-data","errorCode":null,"errorMessage":"error reading multipart data","messagePattern":"error reading multipart data","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdb.go","lineNumber":775,"sourceCode":"\t// Set up the multipart reader based on the boundary.\n\tmultipartReader := multipart.NewReader(resp.Body, params[\"boundary\"])\n\tfor {\n\t\tp, err := multipartReader.NextPart()\n\t\tif err == io.EOF {\n\t\t\tbreak // processed all parts\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, \"\", errors.Wrap(err, \"error reading next multipart\")\n\t\t}\n\n\t\tdefer p.Close()\n\n\t\tcouchdbLogger.Debugf(\"[%s] part header=%s\", dbclient.dbName, p.Header)\n\n\t\tif p.Header.Get(\"Content-Type\") == \"application/json\" {\n\t\t\tpartdata, err := io.ReadAll(p)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, \"\", errors.Wrap(err, \"error reading multipart data\")\n\t\t\t}\n\t\t\tcouchDoc.jsonValue = partdata\n\t\t\tcontinue\n\t\t}\n\n\t\t// Create an attachment structure and load it.\n\t\tattachment := &attachmentInfo{}\n\t\tattachment.ContentType = p.Header.Get(\"Content-Type\")\n\t\tcontentDispositionParts := strings.Split(p.Header.Get(\"Content-Disposition\"), \";\")\n\n\t\tif strings.TrimSpace(contentDispositionParts[0]) != \"attachment\" {\n\t\t\tcontinue\n\t\t}\n\n\t\tswitch p.Header.Get(\"Content-Encoding\") {\n\t\tcase \"gzip\": // See if the part is gzip encoded\n\n\t\t\tvar respBody []byte","sourceCodeStart":757,"sourceCodeEnd":793,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdb.go#L757-L793","documentation":"While iterating the multipart response from CouchDB, the JSON part (Content-Type application/json) is read with io.ReadAll. This error wraps a read failure of the JSON part body, indicating the document payload could not be fully read from the stream.","triggerScenarios":"BatchRetrieveDocuments encountering a broken/truncated response stream while reading the JSON portion of a document: connection reset mid-read, CouchDB closing the connection, or timeouts.","commonSituations":"Large documents exceeding proxy body limits; network instability to CouchDB; CouchDB restarting during bulk document retrieval.","solutions":["Retry the query; transient stream failures typically clear on retry","Check network path (proxies, LBs) for body size limits or idle timeouts and raise them","Inspect CouchDB logs for errors/restarts coinciding with the failure","Reduce batch sizes or document size if large payloads correlate with failures"],"exampleFix":"// before\ndocs, _, err := client.BatchRetrieveDocuments(keys)\n// after\nif err != nil && strings.Contains(err.Error(), \"error reading multipart\") {\n    time.Sleep(500 * time.Millisecond)\n    docs, _, err = client.BatchRetrieveDocuments(keys) // retry once\n}","handlingStrategy":"retry","validationCode":"resp, err := http.Head(couchURL + \"/\" + dbName)\nif err != nil || resp.StatusCode != 200 { return errors.New(\"CouchDB/database not reachable\") }","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"error reading multipart data\") {\n    if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, io.EOF) {\n        time.Sleep(time.Second)\n        return retry(...) // truncated stream: retry the read\n    }\n    return err\n}","preventionTips":["Raise proxy body-size and idle-timeout limits","Keep document sizes moderate; monitor large docs","Enable retries around bulk retrieval calls","Watch CouchDB logs for restarts during heavy reads"],"tags":["couchdb","io","multipart","network"],"backgroundTag":"malformed-multipart-response","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}