hyperledger/fabric · error

unsupported structure field kind %v for serialization for fi

Error message

unsupported structure field kind %v for serialization for field %s

What it means

Any struct field whose kind is not string, int64, slice-of-bytes, or proto pointer falls into the default branch of SerializableChecks and is rejected with this error, which reports the offending kind and field name. This is the terminal validation for unsupported field kinds.

Source

Thrown at core/chaincode/lifecycle/serializer.go:105

	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)
	}

	metadata, ok, err := s.DeserializeMetadata(namespace, name, state)
	if err != nil {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Convert unsupported fields to int64 (integers), string, []byte, or proto pointer
  2. Encode bools/maps into []byte via json.Marshal before serializing
  3. Audit the struct so every field kind matches the serializer's supported set

Example fix

// before
type Def struct { Enabled bool; Labels map[string]string }
// after
type Def struct { EnabledBytes []byte; LabelsBytes []byte } // json.Marshal encoded
Defensive patterns

Strategy: validation

Validate before calling

func checkFieldKinds(v any) error {
  t := reflect.TypeOf(v).Elem()
  for i := 0; i < t.NumField(); i++ {
    k := t.Field(i).Type.Kind()
    switch k {
    case reflect.String, reflect.Int64, reflect.Slice, reflect.Pointer:
    default:
      return fmt.Errorf("field %s kind %v unsupported", t.Field(i).Name, k)
    }
  }
  return nil
}

Type guard

func isSerializableKind(k reflect.Kind) bool {
  return k == reflect.String || k == reflect.Int64 || k == reflect.Slice || k == reflect.Pointer
}

Try / catch

_, _, err := s.SerializableChecks(input)
if err != nil && strings.Contains(err.Error(), "unsupported structure field kind") {
  // replace the offending field with a supported kind
}

Prevention

When it happens

Trigger: Fields of kind bool, float64, uint64, map, interface, struct (non-pointer), etc. in a struct handed to Serialize/IsSerialized/IsMetadataSerialized/Deserialize.

Common situations: Using bool flags or map[string]string fields in chaincode metadata structs; switching an int64 field to uint64 or float64 during refactoring.

Related errors


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