hyperledger/fabric · error
field [%s] is not valid for the CouchDB state database
Error message
field [%s] is not valid for the CouchDB state database
What it means
This error is thrown by checkReservedFieldsNotPresent when a JSON value destined for the CouchDB state database contains a field named 'version' or any field whose name begins with an underscore. CouchDB reserves underscore-prefixed fields (e.g. _id, _rev) and Hyperledger Fabric uses 'version' internally, so user-supplied state JSON must never contain them. The check runs before the value is wrapped into a couchDoc.
Source
Thrown at core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdoc_conv.go:53
type jsonValue map[string]any
func tryCastingToJSON(b []byte) (isJSON bool, val jsonValue) {
var jsonVal map[string]any
err := json.Unmarshal(b, &jsonVal)
return err == nil, jsonVal
}
func castToJSON(b []byte) (jsonValue, error) {
var jsonVal map[string]any
err := json.Unmarshal(b, &jsonVal)
err = errors.Wrap(err, "error unmarshalling json data")
return jsonVal, err
}
func (v jsonValue) checkReservedFieldsNotPresent() error {
for fieldName := range v {
if fieldName == versionField || strings.HasPrefix(fieldName, "_") {
return errors.Errorf("field [%s] is not valid for the CouchDB state database", fieldName)
}
}
return nil
}
func (v jsonValue) removeRevField() {
delete(v, revField)
}
func (v jsonValue) toBytes() ([]byte, error) {
jsonBytes, err := json.Marshal(v)
err = errors.Wrap(err, "error marshalling json data")
return jsonBytes, err
}
func couchDocToKeyValue(doc *couchDoc) (*keyValue, error) {
docFields, err := validateAndRetrieveFields(doc)
if err != nil {View on GitHub (pinned to 2736b63f8f)
Solutions
- Rename the offending field in the chaincode value, e.g. from 'version' to 'docVersion' or '_rev' to 'rev'
- Strip underscore-prefixed metadata fields from the JSON before calling PutState
- Add a serialization layer in the chaincode that sanitizes keys before writing state
Example fix
// before
value := map[string]interface{}{"version": "v1", "_rev": "1-abc"}
jsonBytes, _ := json.Marshal(value)
stub.PutState(key, jsonBytes)
// after
value := map[string]interface{}{"docVersion": "v1", "rev": "1-abc"}
jsonBytes, _ := json.Marshal(value)
stub.PutState(key, jsonBytes) Defensive patterns
Strategy: validation
Validate before calling
func safeForCouchState(v map[string]interface{}) error {
for k := range v {
if k == "version" || strings.HasPrefix(k, "_") {
return fmt.Errorf("field [%s] not allowed in state JSON", k)
}
}
return nil
} Type guard
func hasReservedFields(v map[string]interface{}) bool {
for k := range v {
if k == "version" || strings.HasPrefix(k, "_") { return true }
}
return false
} Prevention
- Never use 'version' or '_'-prefixed names in state JSON schemas
- Sanitize application documents before writing to ledger state
- Keep CouchDB metadata fields out of chaincode value models
- Add unit tests asserting key sets of stored documents
When it happens
Trigger: A chaincode PutState writes a JSON value (via the value-hash or JSON state handling) whose key set includes 'version' or any '_'-prefixed key, and that value passes through jsonValue validation during commit validation.
Common situations: Porting application documents that already use CouchDB-style metadata (_id, _rev, _design) or a domain field literally named 'version' (document versioning schemas) directly into chaincode state without renaming the fields.
Related errors
- version field %s was not found
- error handling CouchDB request. Error:%s, Status Code:%v,
- error marshalling json data
- failed to unmarshal savepoint data
- failed to unmarshal channel metadata
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/0f126ca276aff540.
Report an issue: GitHub.