hyperledger/fabric · error
failed to marshal savepoint data
Error message
failed to marshal savepoint data
What it means
encodeSavepoint serializes couchSavepointData (block and tx number) to JSON for persisting the ledger's latest savepoint in CouchDB. Failures are wrapped with 'failed to marshal savepoint data'. With plain uint64 fields this essentially cannot fail unless the struct or JSON library behaves abnormally.
Source
Thrown at core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdoc_conv.go:213
ChannelName string `json:"ChannelName"`
// namespace to namespaceDBInfo mapping
NamespaceDBsInfo map[string]*namespaceDBInfo `json:"NamespaceDBsInfo"`
}
type namespaceDBInfo struct {
Namespace string `json:"Namespace"`
DBName string `json:"DBName"`
}
func encodeSavepoint(height *version.Height) (*couchDoc, error) {
var err error
var savepointDoc couchSavepointData
// construct savepoint document
savepointDoc.BlockNum = height.BlockNum
savepointDoc.TxNum = height.TxNum
savepointDocJSON, err := json.Marshal(savepointDoc)
if err != nil {
err = errors.Wrap(err, "failed to marshal savepoint data")
logger.Errorf("%+v", err)
return nil, err
}
return &couchDoc{jsonValue: savepointDocJSON, attachments: nil}, nil
}
func decodeSavepoint(couchDoc *couchDoc) (*version.Height, error) {
savepointDoc := &couchSavepointData{}
if err := json.Unmarshal(couchDoc.jsonValue, &savepointDoc); err != nil {
err = errors.Wrap(err, "failed to unmarshal savepoint data")
logger.Errorf("%+v", err)
return nil, err
}
return &version.Height{BlockNum: savepointDoc.BlockNum, TxNum: savepointDoc.TxNum}, nil
}
func encodeChannelMetadata(metadataDoc *channelMetadata) (*couchDoc, error) {
metadataJSON, err := json.Marshal(metadataDoc)View on GitHub (pinned to 2736b63f8f)
Solutions
- Read the wrapped cause from the Errorf log to identify the failing field in couchSavepointData
- Ensure couchSavepointData contains only JSON-serializable primitive fields
- Retry the commit; if persistent, rebuild the peer binary from a stock Fabric release
Example fix
// before
type couchSavepointData struct {
BlockNum uint64
Conn chan struct{} // not serializable
}
// after
type couchSavepointData struct {
BlockNum uint64
TxNum uint64
} Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := json.Marshal(savepointDoc); err != nil {
return fmt.Errorf("savepoint doc not serializable: %w", err)
} Try / catch
doc, err := encodeSavepoint(height)
if err != nil {
logger.Errorf("savepoint encode failed: %+v", err)
return err
} Prevention
- Keep couchSavepointData limited to primitive fields
- Rebuild peers from stock Fabric sources
- Log the wrapped cause with %+v for diagnosis
When it happens
Trigger: recordSavepoint calls encodeSavepoint and json.Marshal returns an error while constructing the savepoint document for the given height.
Common situations: Custom builds where couchSavepointData gained non-JSON-serializable fields (channels, funcs, cycles), or corrupted dependencies/JSON library behavior.
Related errors
- error marshalling json data
- failed to unmarshal savepoint data
- failed to marshal channel metadata
- failed to marshal dataformatInfo [%#v]
- failed to unmarshal channel metadata
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/5ebca3f58ba4381e.
Report an issue: GitHub.