hyperledger/fabric · error

failed to unmarshal channel metadata

Error message

failed to unmarshal channel metadata

What it means

decodeChannelMetadata parses the channel metadata JSON stored in CouchDB back into a channelMetadata struct. Failure means the stored metadata document is corrupt or not in the expected schema, wrapped as 'failed to unmarshal channel metadata'; readChannelMetadata then fails.

Solutions

  1. Inspect and correct the channel metadata document in CouchDB (it should contain the data format version field)
  2. Restore the state database from a valid backup
  3. If unrecoverable, rebuild the ledger database so metadata is rewritten at open time

Example fix

// before (corrupt doc)
{"DataFormatVersion": 2.5}
// after
{"DataFormatVersion": "2.0"}
Defensive patterns

Strategy: try-catch

Validate before calling

func validChannelMetadataJSON(b []byte) bool {
    var m struct{ DataFormatVersion string }
    return json.Unmarshal(b, &m) == nil
}

Try / catch

md, err := decodeChannelMetadata(doc)
if err != nil {
    return nil, fmt.Errorf("channel metadata corrupt; restore DB from backup: %w", err)
}

Prevention

When it happens

Trigger: readChannelMetadata fetches the channel metadata couchDoc and its jsonValue cannot be unmarshaled into channelMetadata (e.g. wrong field types, non-JSON content, wrong document retrieved).

Common situations: Manual modification of the metadata document in CouchDB, restoring databases from backups of a different Fabric version, or accidental overwrites by external tooling.

Related errors


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

Appendix: source

Thrown at core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdoc_conv.go:243

		return nil, err
	}
	return &version.Height{BlockNum: savepointDoc.BlockNum, TxNum: savepointDoc.TxNum}, nil
}

func encodeChannelMetadata(metadataDoc *channelMetadata) (*couchDoc, error) {
	metadataJSON, err := json.Marshal(metadataDoc)
	if err != nil {
		err = errors.Wrap(err, "failed to marshal channel metadata")
		logger.Errorf("%+v", err)
		return nil, err
	}
	return &couchDoc{jsonValue: metadataJSON, attachments: nil}, nil
}

func decodeChannelMetadata(couchDoc *couchDoc) (*channelMetadata, error) {
	metadataDoc := &channelMetadata{}
	if err := json.Unmarshal(couchDoc.jsonValue, &metadataDoc); err != nil {
		err = errors.Wrap(err, "failed to unmarshal channel metadata")
		logger.Errorf("%+v", err)
		return nil, err
	}
	return metadataDoc, nil
}

type dataformatInfo struct {
	Version string `json:"Version"`
}

func encodeDataformatInfo(dataFormatVersion string) (*couchDoc, error) {
	var err error
	dataformatInfo := &dataformatInfo{
		Version: dataFormatVersion,
	}
	dataformatInfoJSON, err := json.Marshal(dataformatInfo)
	if err != nil {
		err = errors.Wrapf(err, "failed to marshal dataformatInfo [%#v]", dataformatInfo)

View on GitHub (pinned to 2736b63f8f)