{"record":{"id":"9c98885b0b827003","repo":"OpenNHP/opennhp","slug":"unsupported-field-type-v","errorCode":null,"errorMessage":"unsupported field type: %v","messagePattern":"unsupported field type: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nhp/core/ztdo/ztdo.go","lineNumber":518,"sourceCode":"\t\t} else {\n\t\t\tvar bytes []byte\n\t\t\tif field.Type().Kind() == reflect.Array { // here assume it's an array of byte.\n\t\t\t\tbytes = make([]byte, field.Len())\n\t\t\t\treflect.Copy(reflect.ValueOf(bytes), field)\n\t\t\t} else if field.Type().Kind() == reflect.Slice {\n\t\t\t\tif field.Type().Elem().Kind() == reflect.Struct {\n\t\t\t\t\tfor j := range field.Len() {\n\t\t\t\t\t\tif err := marshal(buf, field.Index(j).Interface()); err != nil {\n\t\t\t\t\t\t\treturn err\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if field.Type().Elem().Kind() == reflect.Uint8 {\n\t\t\t\t\tbytes = field.Interface().([]byte)\n\t\t\t\t} else {\n\t\t\t\t\treturn fmt.Errorf(\"unsupported field type: %v in slice\", field.Type().Elem().Kind())\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn fmt.Errorf(\"unsupported field type: %v\", field.Type().Kind())\n\t\t\t}\n\n\t\t\tif _, err := buf.Write(bytes); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// unmarshal recursively deserializes binary data from a file into a Go struct\nfunc unmarshal(f *os.File, data any) error {\n\trValues := reflect.ValueOf(data)\n\trTypes := reflect.TypeOf(data)\n\tif rValues.Kind() == reflect.Pointer {\n\t\trTypes = rTypes.Elem()\n\t\trValues = rValues.Elem()","sourceCodeStart":500,"sourceCodeEnd":536,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/nhp/core/ztdo/ztdo.go#L500-L536","documentation":"marshal supports only struct fields and (for slices) uint8-element slices; a field whose kind is anything else — map, chan, func, interface, string at top level of the field type, etc. — has no encoding in this binary format and is rejected with this error at the outer else branch.","triggerScenarios":"Marshaling a struct with a field of kind map, chan, func, interface, complex, or an unsafe/unsupported kind; also triggered when a non-slice, non-struct field type falls through all supported branches.","commonSituations":"Leaving a debug/logger or sync.Mutex field on a struct passed to toBuffer; embedding a map for extra attributes; passing structs containing time.Time in a codebase where the expected pattern is fixed-size fields (time.Time is a struct and recurses into its unexported fields, often failing deeper).","solutions":["Remove the unsupported field from the struct or keep it unexported and store its encoded form in a []byte field.","Replace maps/chans/interfaces with explicit fixed-size fields or byte slices.","Split the struct: serialize only the wire-format portion with toBuffer, keep the rest in application memory.","Consult the marshal implementation's supported kinds and mirror them in your struct design."],"exampleFix":"// before\ntype H struct {\n    mu sync.Mutex // unsupported field kind\n}\n// after\ntype H struct {\n    // no locks/maps on the wire struct\n    Flags uint64\n}","handlingStrategy":"type-guard","validationCode":"allowed := map[reflect.Kind]bool{reflect.Struct: true, reflect.Uint8: true, reflect.Slice: true, reflect.Array: true /* plus other supported fixed-size kinds */}\nrv := reflect.TypeOf(MyStruct{})\nfor i := 0; i < rv.NumField(); i++ {\n    if !allowed[rv.Field(i).Type.Kind()] {\n        panic(\"unsupported ztdo field kind: \" + rv.Field(i).Name)\n    }\n}","typeGuard":"k := reflect.TypeOf(field).Kind()\nif !allowed[k] { return fmt.Errorf(\"field kind %v not ztdo-serializable\", k) }","tryCatchPattern":"if err := toBuffer(s); err != nil {\n    if strings.Contains(err.Error(), \"unsupported field type\") {\n        return fmt.Errorf(\"%T contains a field kind without a wire encoding\", s)\n    }\n    return err\n}","preventionTips":["Keep wire structs free of maps, chans, funcs, interfaces and mutexes","Separate transport structs from application structs","Add a unit test that round-trips every wire struct through toBuffer/toStructure"],"tags":["reflection","serialization","go","unsupported-type"],"backgroundTag":"unsupported-operation","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}