hyperledger/fabric · error
could not marshal field %s
Error message
could not marshal field %s
What it means
During Serialize, a non-nil proto pointer field is marshaled with the configured Marshaler; if proto marshaling fails (invalid message, marshaler misconfigured), the error is wrapped as 'could not marshal field <name>'. Unlike index 552, this occurs only for non-nil fields whose contents are invalid.
Source
Thrown at core/chaincode/lifecycle/serializer.go:159
fieldName := value.Type().Field(i).Name
fieldValue := value.Field(i)
keyName := FieldKey(namespace, name, fieldName)
stateData := &lb.StateData{}
switch fieldValue.Kind() {
case reflect.String:
stateData.Type = &lb.StateData_String_{String_: fieldValue.String()}
case reflect.Int64:
stateData.Type = &lb.StateData_Int64{Int64: fieldValue.Int()}
case reflect.Slice:
stateData.Type = &lb.StateData_Bytes{Bytes: fieldValue.Bytes()}
case reflect.Pointer:
var bin []byte
if !fieldValue.IsNil() {
bin, err = s.Marshaler.Marshal(fieldValue.Interface().(proto.Message))
if err != nil {
return errors.Wrapf(err, "could not marshal field %s", fieldName)
}
}
stateData.Type = &lb.StateData_Bytes{Bytes: bin}
// Note, other field kinds and bad types have already been checked by SerializableChecks
}
marshaledFieldValue, err := s.Marshaler.Marshal(stateData)
if err != nil {
return errors.WithMessagef(err, "could not marshal value for key %s", keyName)
}
if existingValue, ok := existingKeys[keyName]; !ok || !bytes.Equal(existingValue, marshaledFieldValue) {
err := state.PutState(keyName, marshaledFieldValue)
if err != nil {
return errors.WithMessage(err, "could not write key into state")
}
}
delete(existingKeys, keyName)View on GitHub (pinned to 2736b63f8f)
Solutions
- Fully initialize the proto message including its oneof before calling Serialize
- Validate the message with msg.ProtoReflect().IsValid() / proto checks before serializing
- Inspect the wrapped inner error (errors.Unwrap) to find the underlying marshal failure
- If a custom Marshaler is installed, verify it handles the message type correctly
Example fix
// before
policy := &pb.ApplicationPolicy{} // oneof unset
s.Serialize(state, metadata, &Def{Policy: policy})
// after
policy := &pb.ApplicationPolicy{Type: &pb.ApplicationPolicy_Policy{Policy: &pb.SignaturePolicyEnvelope{Version: 0}}}
s.Serialize(state, metadata, &Def{Policy: policy}) Defensive patterns
Strategy: try-catch
Validate before calling
if fieldMsg != nil && !fieldMsg.ProtoReflect().IsValid() {
return errors.New("proto field invalid before Serialize")
} Type guard
func isMarshalableProto(msg proto.Message) bool { return msg != nil && msg.ProtoReflect().IsValid() } Try / catch
err := s.Serialize(state, metadata, def)
if err != nil && strings.Contains(err.Error(), "could not marshal field") {
var inner error
if e, ok := err.(interface{ Unwrap() error }); ok { inner = e.Unwrap() }
// inspect inner marshal error, fix the named field's proto message
} Prevention
- Fully populate proto messages (especially oneofs) before Serialize
- Validate messages with IsValid() prior to serialization
- Check the wrapped inner error to identify the failing field
- Test Serialize paths whenever proto definitions change
When it happens
Trigger: Serialize on a struct whose proto pointer field is non-nil but internally invalid (e.g. a oneof unset / invalid required data) so s.Marshaler.Marshal returns an error.
Common situations: Constructing an EndorsementPolicy/ApplicationPolicy message incorrectly (empty oneof) before committing a chaincode definition; custom Marshaler functions returning errors for certain message types.
Related errors
- failed to marshal args
- proto: Marshal called with nil
- unsupported pointer type %v for field %s (must be proto)
- failed to marshal updated readiness result
- error marshaling proposal
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/fbaa222e2fb04371.
Report an issue: GitHub.