hyperledger/fabric · error

error marshalling json data

Error message

error marshalling json data

What it means

toBytes serializes a jsonValue map into JSON bytes for storage in CouchDB. If json.Marshal fails, the underlying error is wrapped with 'error marshalling json data'. This is nearly always caused by an unsupported value type (channels, funcs, cycles) rather than malformed field names.

Source

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

	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 {
		return nil, err
	}
	version, metadata, err := decodeVersionAndMetadata(docFields.versionAndMetadata)
	if err != nil {
		return nil, err
	}
	return &keyValue{
		docFields.id, docFields.revision,
		&statedb.VersionedValue{
			Value:    docFields.value,
			Version:  version,
			Metadata: metadata,

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Inspect the wrapped cause in the log (%+v prints the original json.Marshal error and offending type)
  2. Ensure the jsonValue only holds JSON-decodable types (map[string]interface{}, string, float64, bool, nil, slices)
  3. Marshal data to JSON at the chaincode boundary so stored values are already plain JSON

Example fix

// before
value := jsonValue{"data": make(chan int)}
bytes, err := value.toBytes()
// after
value := jsonValue{"data": 42}
bytes, err := value.toBytes()
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := json.Marshal(value); err != nil {
    return fmt.Errorf("value not JSON-marshalable: %w", err)
}

Type guard

func isJSONSafe(v interface{}) bool {
    _, err := json.Marshal(v)
    return err == nil
}

Try / catch

bytes, err := v.toBytes()
if err != nil {
    logger.Errorf("toBytes failed: %+v", err)
    return fmt.Errorf("state value serialization failed: %w", err)
}

Prevention

When it happens

Trigger: jsonValue contains a value that the encoding/json package cannot marshal, such as a channel, function, complex number, or a cyclic structure, when the value is converted to bytes for a couchDoc.

Common situations: Custom code paths or tests constructing jsonValue from arbitrary Go structures instead of decoded JSON; injecting unsupported Go types into the state value map.

Related errors


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