hyperledger/fabric · error

version field was not found

Error message

version field %s was not found

What it means

couchdb stores a Fabric-internal 'version' field in every state document; validateAndRetrieveFields requires it to reconstruct versioned keys/values. When a document read from the CouchDB state database lacks the version field, this error is returned, meaning the document was not written by the ledger's expected format.

Solutions

  1. Remove the foreign/manually created document from the ledger database or move it to a separate database
  2. Verify the state database was created by the same Fabric version; if not, re-create the ledger or run the appropriate data migration
  3. Restore the ledger database from a valid backup that includes the internal 'version' fields
Defensive patterns

Strategy: validation

Validate before calling

func docHasVersion(doc map[string]interface{}) bool {
    _, ok := doc["version"]
    return ok
}

Type guard

func isLedgerWrittenDoc(jsonBytes []byte) bool {
    var m map[string]interface{}
    if json.Unmarshal(jsonBytes, &m) != nil { return false }
    _, ok := m["version"]
    return ok
}

Try / catch

kv, err := couchDocToKeyValue(doc)
if err != nil {
    return nil, fmt.Errorf("unexpected document in state DB (missing version field?): %w", err)
}

Prevention

When it happens

Trigger: couchDocToKeyValue reads a couchDoc whose decoded JSON has no 'version' field — e.g. a manually created CouchDB document, a document from a different Fabric version/format, or a corrupted/deleted field.

Common situations: Operators editing CouchDB documents directly (Fauxton/curl), restoring state DBs from partial backups, mixing databases created by incompatible Fabric releases, or placing application documents into the ledger's database.

Related errors


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

Appendix: source

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

	value              []byte
	versionAndMetadata string
}

func validateAndRetrieveFields(doc *couchDoc) (*couchDocFields, error) {
	jsonDoc := make(jsonValue)
	decoder := json.NewDecoder(bytes.NewBuffer(doc.jsonValue))
	decoder.UseNumber()
	if err := decoder.Decode(&jsonDoc); err != nil {
		return nil, err
	}

	docFields := &couchDocFields{}
	docFields.id = jsonDoc[idField].(string)
	if jsonDoc[revField] != nil {
		docFields.revision = jsonDoc[revField].(string)
	}
	if jsonDoc[versionField] == nil {
		return nil, fmt.Errorf("version field %s was not found", versionField)
	}
	docFields.versionAndMetadata = jsonDoc[versionField].(string)

	delete(jsonDoc, idField)
	delete(jsonDoc, revField)
	delete(jsonDoc, versionField)

	var err error
	if doc.attachments == nil {
		docFields.value, err = json.Marshal(jsonDoc)
		return docFields, err
	}
	for _, attachment := range doc.attachments {
		if attachment.Name == binaryWrapper {
			docFields.value = attachment.AttachmentBytes
		}
	}
	return docFields, err

View on GitHub (pinned to 2736b63f8f)