hyperledger/fabric · error
unsupported pointer type %v for field %s (must be proto)
Error message
unsupported pointer type %v for field %s (must be proto)
What it means
Pointer fields in lifecycle state structs must implement proto.Message. If a field is a pointer to something else (e.g. *string, *int64, custom struct pointer), SerializableChecks fails with this error naming the element type and field.
Source
Thrown at core/chaincode/lifecycle/serializer.go:102
if value.Kind() != reflect.Struct {
return reflect.Value{}, nil, errors.Errorf("must be pointers to struct, but got pointer to %v", value.Kind())
}
allFields := make([]string, value.NumField())
for i := 0; i < value.NumField(); i++ {
fieldName := value.Type().Field(i).Name
fieldValue := value.Field(i)
allFields[i] = fieldName
switch fieldValue.Kind() {
case reflect.String:
case reflect.Int64:
case reflect.Slice:
if fieldValue.Type().Elem().Kind() != reflect.Uint8 {
return reflect.Value{}, nil, errors.Errorf("unsupported slice type %v for field %s", fieldValue.Type().Elem().Kind(), fieldName)
}
case reflect.Pointer:
if !fieldValue.Type().Implements(ProtoMessageType) {
return reflect.Value{}, nil, errors.Errorf("unsupported pointer type %v for field %s (must be proto)", fieldValue.Type().Elem(), fieldName)
}
default:
return reflect.Value{}, nil, errors.Errorf("unsupported structure field kind %v for serialization for field %s", fieldValue.Kind(), fieldName)
}
}
return value, allFields, nil
}
// Serialize takes a pointer to a struct, and writes each of its fields as keys
// into a namespace. It also writes the struct metadata (if it needs updating)
// and, deletes any keys in the namespace which are not found in the struct.
// Note: If a key already exists for the field, and the value is unchanged, then
// the key is _not_ written to.
func (s *Serializer) Serialize(namespace, name string, structure any, state ReadWritableState) error {
value, allFields, err := s.SerializableChecks(structure)
if err != nil {
return errors.WithMessagef(err, "structure for namespace %s/%s is not serializable", namespace, name)
}View on GitHub (pinned to 2736b63f8f)
Solutions
- Make the field a protobuf message pointer (generate from a .proto so it implements proto.Message)
- Change the field to a non-pointer supported kind (string, int64, []byte) if no proto is needed
- Nil-check semantics: Serialize stores nil bytes for nil proto pointers, which is supported — only non-proto pointers are rejected
Example fix
// before
type Def struct { Policy *MyGoPolicy }
// after
type Def struct { Policy *pb.ApplicationPolicy } // implements proto.Message Defensive patterns
Strategy: type-guard
Validate before calling
func allPointersAreProto(v any) error {
t := reflect.TypeOf(v).Elem()
for i := 0; i < t.NumField(); i++ {
f := t.Field(i).Type
if f.Kind() == reflect.Pointer && !f.Implements(reflect.TypeFor[proto.Message]()) {
return fmt.Errorf("field %s pointer is not proto.Message", t.Field(i).Name)
}
}
return nil
} Type guard
func isProtoPointer(f reflect.Type) bool { return f.Kind() == reflect.Pointer && f.Implements(reflect.TypeFor[proto.Message]()) } Try / catch
_, _, err := s.SerializableChecks(input)
if err != nil && strings.Contains(err.Error(), "must be proto") {
// convert the field to a proto message pointer or supported kind
} Prevention
- Use generated protobuf types for pointer fields
- Avoid optional *string/*int64 fields in state structs
- Compile-time assert: var _ proto.Message = (*pb.MyMsg)(nil)
When it happens
Trigger: Struct field like *Config or *int64 passed through Serialize/Deserialize/IsSerialized where *Config does not implement proto.Message.
Common situations: Adding a pointer to an internal Go struct or optional scalar to a chaincode definition/metadata struct; partially converting a struct to protobuf style where one field was left as a plain pointer.
Related errors
- proto: Marshal called with nil
- unsupported slice type %v for field %s
- unsupported structure field kind %v for serialization for fi
- could not marshal field %s
- error marshaling proposal
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/48e5992e395a0496.
Report an issue: GitHub.