hyperledger/fabric · error
Failed opening file %s: %v
Error message
Failed opening file %s: %v
What it means
After reading the _all_docs bulk-response body, the client unmarshals it into batchRetrieveDocMetadataResponse. If the body is not valid JSON or its rows do not match the expected shape (id, rev, doc metadata with version), json.Unmarshal fails and the error is wrapped as 'error unmarshalling json data', aborting retrieval of ledger versions for the batch of keys.
Source
Thrown at cmd/common/comm/config.go:69
}
certBytes, err = loadFile(conf.CertPath)
if err != nil {
return comm.SecureOptions{}, errors.WithStack(err)
}
}
return comm.SecureOptions{
Key: keyBytes,
Certificate: certBytes,
UseTLS: true,
ServerRootCAs: [][]byte{caBytes},
RequireClientCert: true,
}, nil
}
func loadFile(path string) ([]byte, error) {
b, err := os.ReadFile(path)
if err != nil {
return nil, errors.Errorf("Failed opening file %s: %v", path, err)
}
return b, nil
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Verify CouchDB username/password (ledger.state.couchDBConfig.username/password) so the server returns real JSON, not an auth error page
- curl -u user:pass -X POST with {"keys":[...]} against /<db>/_all_docs to inspect the actual body
- Check for proxies/interceptors returning HTML and bypass them
- Confirm Fabric/CouchDB version compatibility
- Enable couchdbLogger debug output to capture the raw response for inspection
Example fix
// before
resp, err := http.Post("http://proxy/db/_all_docs", ...) // proxy 502 HTML body
json.Unmarshal(raw, &jsonResponse) // fails
// after
if ct := resp.Header.Get("Content-Type"); !strings.HasPrefix(ct, "application/json") {
return nil, fmt.Errorf("unexpected CouchDB response: %.200s", raw)
}
err2 := json.Unmarshal(jsonResponseRaw, &jsonResponse) Defensive patterns
Strategy: type-guard
Validate before calling
raw, _ := io.ReadAll(resp.Body)
if !json.Valid(raw) {
return fmt.Errorf("non-JSON _all_docs response: %.200s", raw)
} Type guard
func isJSONResponse(resp *http.Response) bool {
ct := resp.Header.Get("Content-Type")
return strings.HasPrefix(ct, "application/json")
} Try / catch
if err != nil && strings.Contains(err.Error(), "error unmarshalling json data") {
// dump raw body at debug level, check auth/proxy, then retry
return fmt.Errorf("bad _all_docs response from CouchDB: %w", err)
} Prevention
- Verify CouchDB credentials so error responses are never silently decoded
- Bypass HTML-emitting proxies for the CouchDB host
- Check Content-Type before decoding server responses
- Keep Fabric and CouchDB versions compatible
- Alert on 401/403/502 statuses from CouchDB in metrics
When it happens
Trigger: CouchDB (or an intermediary) returns a non-JSON body for the _all_docs POST — e.g. 401/403 HTML or text error page, proxy captive-portal response, truncated JSON from a dropped connection — or a body whose rows[] entries contain unexpected types.
Common situations: Wrong CouchDB credentials causing an error response that still gets decoded, an LB returning its own HTML error page, version mismatch where the server's _all_docs response shape differs, corrupted network transfer.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- too few arguments
- config isn't valid
- incorrect number of arguments
- connection.json not found in source folder: %s
- failed to marshal config
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/7261435648251295.
Report an issue: GitHub.