OpenNHP/opennhp · error
unsupported element type
Error message
unsupported element type: %v in slice
What it means
When unmarshal encounters a slice-typed field, it only knows how to read elements for supported element kinds (uint8 byte-slices via the f.Read branch, or fixed-size element types handled above). Any other slice element kind cannot be decoded from the stream, so it returns this error naming the element kind.
Solutions
- Change the destination field to []byte and decode manually after unmarshal.
- Use a fixed-size array (e.g. [N]byte) if the length is known.
- Bump/align the struct definition with what the writer actually serialized.
- Decode the byte blob into typed values (encoding/binary, json.Unmarshal) post-read.
Example fix
// before
var h struct{ Tags []string }
err := toStructure(f, &h) // unsupported element type
// after
var h struct{ TagsBytes []byte }
err := toStructure(f, &h)
var tags []string
json.Unmarshal(h.TagsBytes, &tags) Defensive patterns
Strategy: type-guard
Validate before calling
t := reflect.TypeOf(dst).Elem()
for i := 0; i < t.NumField(); i++ {
ft := t.Field(i).Type
if ft.Kind() == reflect.Slice && ft.Elem().Kind() != reflect.Uint8 {
panic("change " + t.Field(i).Name + " to []byte and decode after unmarshal")
}
} Type guard
ft := reflect.TypeOf(dst).Elem().Field(i).Type
if ft.Kind() == reflect.Slice && ft.Elem().Kind() != reflect.Uint8 { /* unsupported for ztdo */ } Try / catch
if err := toStructure(f, &h); err != nil {
if strings.Contains(err.Error(), "unsupported element type") {
return fmt.Errorf("slice field in %T needs a []byte representation", h)
}
return err
} Prevention
- Round-trip test every struct through marshal/unmarshal in CI
- Keep reader and writer struct definitions in one shared package
- Convert typed slices to []byte before writing and back after reading
When it happens
Trigger: Deserializing into a struct with a slice field whose element type is not uint8 and not one of the fixed-size supported element kinds — e.g. []string, []float32, []int64 read back from a ztdo file.
Common situations: Round-tripping a struct whose write-side error was 'fixed' with json-in-bytes but keeping the original typed field; schema drift where a newer writer emits a slice type this reader does not support; structs shared between ztdo and JSON APIs.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- unsupported field type
- unsupported field type
- data must be a struct
- data must be a pointer
- unknown remote provider
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/212d572a541de599.
Report an issue: GitHub.
Appendix: source
Thrown at nhp/core/ztdo/ztdo.go:605
value.Set(newValue)
err := unmarshal(f, value.Index(value.Len()-1).Addr().Interface())
if err != nil {
return err
}
if !lengthContinueIndicator { // more data to be read to construct element in current slice
break
}
}
} else if field.Type.Elem().Kind() == reflect.Uint8 { // if the elment in slice is a byte, there MUST be lengthFor tag to be parsed before.
length := lengthMap[field.Name]
bytes := make([]byte, length)
_, err := f.Read(bytes)
if err != nil {
return err
}
setBytes(value, bytes)
} else {
return fmt.Errorf("unsupported element type: %v in slice", field.Type.Elem().Kind())
}
} else {
return fmt.Errorf("unsupported field type: %v", field.Type.Kind())
}
}
}
return nil
}
// toBuffer provides unified way to serialize a Go struct into bytes buffer
func toBuffer(data any) *bytes.Buffer {
buf := bytes.NewBuffer(nil)
_ = marshal(buf, data)
return buf
}
// toStructure provides unified way to deserialize bytes from a file into a Go structView on GitHub (pinned to 6e04ca5ff0)