AlexxIT/go2rtc · error

tlv8: not implemented:

Error message

tlv8: not implemented: 

What it means

tlv8.Marshal only supports top-level values whose reflect kind is Slice or Struct (after dereferencing a pointer). Any other kind (map, string, int, bool, etc.) has no TLV8 encoding defined in this library, so it returns this error naming the unsupported kind. TLV8 encoding in HAP is defined for tagged struct/slice-of-struct values only.

Solutions

  1. Wrap the payload in a struct with `tlv8:"<tag>"` field tags and marshal that struct.
  2. Pass a slice of tagged structs (each element becomes a TLV8 record).
  3. Dereference or type-assert the value to a struct/slice before calling Marshal.
  4. Check the value's kind at runtime and reject unsupported types before calling Marshal.

Example fix

// before
data, err := tlv8.Marshal(map[string]string{"State": "1"}) // tlv8: not implemented: map

// after
type payload struct {
    State byte `tlv8:"6"`
}
data, err := tlv8.Marshal(payload{State: 1})
Defensive patterns

Strategy: type-guard

Validate before calling

func marshalable(v any) bool {
    k := reflect.ValueOf(v).Kind()
    if k == reflect.Pointer { k = reflect.ValueOf(v).Elem().Kind() }
    return k == reflect.Slice || k == reflect.Struct
}
// guard: if !marshalable(v) { return fmt.Errorf("tlv8 marshal needs struct or slice, got %T", v) }

Type guard

func isStructOrSlice(v any) bool {
    rv := reflect.ValueOf(v)
    if rv.Kind() == reflect.Pointer { rv = rv.Elem() }
    return rv.Kind() == reflect.Slice || rv.Kind() == reflect.Struct
}

Try / catch

b, err := tlv8.Marshal(v)
if err != nil {
    return fmt.Errorf("tlv8.Marshal %T: %w", v, err)
}

Prevention

When it happens

Trigger: Calling tlv8.Marshal (directly or via MarshalBase64/MarshalReader, or indirectly from Dial/Pair/PairSetup/PairVerify) with a value whose dereferenced kind is not Slice or Struct, e.g. tlv8.Marshal(map[string]int{...}) or tlv8.Marshal("foo").

Common situations: Passing a JSON-decoded map[string]any instead of a typed struct; forgetting a pointer dereference layer such that kind stays Interface; marshalling a bare string/number payload; copying a struct into an interface used as `any` holding a non-struct type.

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 AlexxIT/go2rtc@c245815e75 (2026-09-07). Data as JSON: /api/errors/253b23a2ee60400a. Report an issue: GitHub.

Appendix: source

Thrown at pkg/hap/tlv8/tlv8.go:55

}

func Marshal(v any) ([]byte, error) {
	value := reflect.ValueOf(v)
	kind := value.Type().Kind()

	if kind == reflect.Pointer {
		value = value.Elem()
		kind = value.Type().Kind()
	}

	switch kind {
	case reflect.Slice:
		return appendSlice(nil, value)
	case reflect.Struct:
		return appendStruct(nil, value)
	}

	return nil, errors.New("tlv8: not implemented: " + kind.String())
}

// separator the most confusing meaning in the documentation.
// It can have a value of 0x00 or 0xFF or even 0x05.
const separator = 0xFF

func appendSlice(b []byte, value reflect.Value) ([]byte, error) {
	for i := 0; i < value.Len(); i++ {
		if i > 0 {
			b = append(b, separator, 0)
		}
		var err error
		if b, err = appendStruct(b, value.Index(i)); err != nil {
			return nil, err
		}
	}
	return b, nil
}

View on GitHub (pinned to c245815e75)