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

  1. Change the destination field to []byte and decode manually after unmarshal.
  2. Use a fixed-size array (e.g. [N]byte) if the length is known.
  3. Bump/align the struct definition with what the writer actually serialized.
  4. 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

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


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 struct

View on GitHub (pinned to 6e04ca5ff0)