hyperledger/fabric · error

error reading next multipart

Error message

error reading next multipart

What it means

When reading a CouchDB document with attachments, BatchRetrieveDocuments/BatchUpdateDocuments parse CouchDB's multipart/mixed response. This error wraps a failure from multipartReader.NextPart(), meaning the multipart body from CouchDB was malformed or the connection broke mid-response.

Source

Thrown at core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdb.go:765

	if !strings.HasPrefix(mediaType, "multipart/") {
		couchDoc.jsonValue, err = io.ReadAll(resp.Body)
		if err != nil {
			return nil, "", errors.Wrap(err, "error reading response body")
		}

		return &couchDoc, revision, nil
	}

	// Handle as attachment.
	// Set up the multipart reader based on the boundary.
	multipartReader := multipart.NewReader(resp.Body, params["boundary"])
	for {
		p, err := multipartReader.NextPart()
		if err == io.EOF {
			break // processed all parts
		}
		if err != nil {
			return nil, "", errors.Wrap(err, "error reading next multipart")
		}

		defer p.Close()

		couchdbLogger.Debugf("[%s] part header=%s", dbclient.dbName, p.Header)

		if p.Header.Get("Content-Type") == "application/json" {
			partdata, err := io.ReadAll(p)
			if err != nil {
				return nil, "", errors.Wrap(err, "error reading multipart data")
			}
			couchDoc.jsonValue = partdata
			continue
		}

		// Create an attachment structure and load it.
		attachment := &attachmentInfo{}
		attachment.ContentType = p.Header.Get("Content-Type")

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Verify connectivity to CouchDB (curl the _all_docs endpoint) and check CouchDB logs for errors at the same timestamp
  2. Retry the failed query — multipart parse failures from transient network issues usually succeed on retry
  3. Remove/increase proxy or load-balancer idle timeouts between peer and CouchDB
  4. Check CouchDB health/resources (memory, max_connections) and scale if it is crashing mid-response

Example fix

// before
client, err := CreateCouchDBClient(...)
docs, _, err := client.BatchRetrieveDocuments(...)
// after (add resilience)
const maxRetries = 3
var docs []*couchdb.CouchDoc
for i := 0; i < maxRetries; i++ {
    docs, _, err = client.BatchRetrieveDocuments(...)
    if err == nil { break }
    time.Sleep(time.Duration(i+1) * time.Second)
}
Defensive patterns

Strategy: retry

Validate before calling

resp, err := http.Get(couchURL + "/_all_dbs")
if err != nil || resp.StatusCode != 200 { return errors.New("CouchDB unreachable or unhealthy before query") }

Try / catch

docs, _, err := client.BatchRetrieveDocuments(keys)
if err != nil && strings.Contains(err.Error(), "error reading next multipart") {
    // transient stream failure: backoff and retry
    time.Sleep(1 * time.Second)
    docs, _, err = client.BatchRetrieveDocuments(keys)
}

Prevention

When it happens

Trigger: Reading documents (with include_docs/attachments) when CouchDB returns a truncated or invalid multipart body: network interruption, CouchDB crash/timeout mid-response, or an intermediary proxy mangling the response.

Common situations: Unstable network between peer and CouchDB; load balancer/proxy with aggressive timeouts; CouchDB under heavy load dropping connections; TLS termination issues.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/abea01300deaad4e. Report an issue: GitHub.