{"record":{"id":"47371e0df5544848","repo":"hyperledger/fabric","slug":"must-be-pointer-to-struct-but-got-non-pointer-v","errorCode":null,"errorMessage":"must be pointer to struct, but got non-pointer %v","messagePattern":"must be pointer to struct, but got non-pointer (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/chaincode/lifecycle/serializer.go","lineNumber":80,"sourceCode":"\n// Serializer is used to write structures into the db and to read them back out.\n// Although it's unfortunate to write a custom serializer, rather than to use something\n// pre-written, like protobuf or JSON, in order to produce precise readwrite sets which\n// only perform state updates for keys which are actually updated (and not simply set\n// to the same value again) custom serialization is required.\ntype Serializer struct {\n\t// Marshaler, when nil uses the standard protobuf impl.\n\t// Can be overridden for test.\n\tMarshaler Marshaler\n}\n\n// SerializableChecks performs some boilerplate checks to make sure the given structure\n// is serializable.  It returns the reflected version of the value and a slice of all\n// field names, or an error.\nfunc (s *Serializer) SerializableChecks(structure any) (reflect.Value, []string, error) {\n\tvalue := reflect.ValueOf(structure)\n\tif value.Kind() != reflect.Pointer {\n\t\treturn reflect.Value{}, nil, errors.Errorf(\"must be pointer to struct, but got non-pointer %v\", value.Kind())\n\t}\n\n\tvalue = value.Elem()\n\tif value.Kind() != reflect.Struct {\n\t\treturn reflect.Value{}, nil, errors.Errorf(\"must be pointers to struct, but got pointer to %v\", value.Kind())\n\t}\n\n\tallFields := make([]string, value.NumField())\n\tfor i := 0; i < value.NumField(); i++ {\n\t\tfieldName := value.Type().Field(i).Name\n\t\tfieldValue := value.Field(i)\n\t\tallFields[i] = fieldName\n\t\tswitch fieldValue.Kind() {\n\t\tcase reflect.String:\n\t\tcase reflect.Int64:\n\t\tcase reflect.Slice:\n\t\t\tif fieldValue.Type().Elem().Kind() != reflect.Uint8 {\n\t\t\t\treturn reflect.Value{}, nil, errors.Errorf(\"unsupported slice type %v for field %s\", fieldValue.Type().Elem().Kind(), fieldName)","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/chaincode/lifecycle/serializer.go#L62-L98","documentation":"SerializableChecks in the lifecycle Serializer requires the input to be a pointer to a struct because it writes each struct field as a separate state key. If reflect.ValueOf(structure).Kind() is not reflect.Pointer, it returns this error reporting the actual kind.","triggerScenarios":"Calling serializer.Serialize or IsSerialized/IsMetadataSerialized with a struct value (not pointer), a map, or a basic type, e.g. Serialize(state, metadata, MyStruct{...}) instead of &MyStruct{...}.","commonSituations":"Passing a struct literal by value to Serialize; refactoring code that changed a pointer parameter to a value; deserializing into a non-pointer type in unit tests.","solutions":["Pass a pointer to the struct: Serialize(state, metadata, &myStruct)","Check the call site type so the argument is T* not T","Wrap the value before calling: obj := MyStruct{...}; s.Serialize(state, metadata, &obj)"],"exampleFix":"// before\nerr := s.Serialize(state, metadata, ChaincodeDefinition{Name: \"cc\"})\n// after\nerr := s.Serialize(state, metadata, &ChaincodeDefinition{Name: \"cc\"})","handlingStrategy":"type-guard","validationCode":"if _, ok := any(v).(*MyStruct); !ok {\n  return errors.New(\"Serialize requires *MyStruct, got value type\")\n}","typeGuard":"func isStructPointer[T any](v any) bool {\n  rv := reflect.ValueOf(v)\n  return rv.Kind() == reflect.Pointer && rv.Elem().Kind() == reflect.Struct\n}","tryCatchPattern":"_, _, err := s.SerializableChecks(input)\nif err != nil && strings.Contains(err.Error(), \"non-pointer\") {\n  // wrap in a pointer and retry\n}","preventionTips":["Always pass &Struct{...} to Serialize/Deserialize","Make serialization helpers take typed pointer parameters so the compiler enforces it","Add unit tests calling SerializableChecks with production structs"],"tags":["fabric","serialization","reflection","type-error"],"backgroundTag":"non-pointer-struct-serialization","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}