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

  1. Verify CouchDB username/password (ledger.state.couchDBConfig.username/password) so the server returns real JSON, not an auth error page
  2. curl -u user:pass -X POST with {"keys":[...]} against /<db>/_all_docs to inspect the actual body
  3. Check for proxies/interceptors returning HTML and bypass them
  4. Confirm Fabric/CouchDB version compatibility
  5. 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

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


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