AlexxIT/go2rtc · error
tlv8: can't find T= ,L= ,V= for
Error message
tlv8: can't find T=%d,L=%d,V=%x for: %s
What it means
tlv8.unmarshalTLV encountered a TLV record whose Tag has no corresponding struct field (fields are matched by decimal tag name, e.g. `"1"`). The record's T, L and hex V are printed along with the target struct name. This happens when decoding TLV8 data containing tags the target struct does not model.
Solutions
- Add a field named after the missing tag (string name of the tag number) to the target struct, or a catch-all map field if supported.
- Upgrade the tlv8/hap library so its structs cover the new tags.
- Dump the failing T,L,V from the error and check which HAP spec tag it corresponds to.
- If the tag is ignorable, pre-filter it from the TLV slice before unmarshalling.
Example fix
// before
type pairVerifyResponse struct {
"1" []byte
"3" []byte
}
// after (device also sends tag 2)
type pairVerifyResponse struct {
"1" []byte
"2" []byte
"3" []byte
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-scan TLV records and drop unknown tags before unmarshalling
func knownOnly(recs []tlv8.Record, known map[byte]bool) []tlv8.Record { ... } Try / catch
err := tlv8.Unmarshal(data, &msg)
if err != nil {
var tlvErr error
if errors.As(err, &tlvErr) && strings.Contains(err.Error(), "can't find T=") {
log.Printf("unknown TLV tag from device: %v", err)
}
return err
} Prevention
- Keep tlv8/hap structs in sync with the devices you deploy
- Prefer decoding into a map/tlv8.Records first to inspect unknown tags
- Log T/L/V from the error message to map against the HAP spec
- Update the library when accessories get firmware upgrades adding new tags
When it happens
Trigger: Unmarshalling a TLV8 blob (e.g. a HAP pairing message) whose tag set includes values not present as fields in the destination struct — typically a device using newer/extra tags than the struct supports.
Common situations: Accessories implementing newer HAP protocol extensions; mismatched struct definitions after a library upgrade; decoding vendor-specific TLVs into a generic struct.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- tlv8: value should be pointer:
- tlv8: wrong size:
- tlv8: zero item
- tlv8: unmarshal zero data
- hap: wrong request: %#v
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/b7cc7e32664c655c.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/hap/tlv8/tlv8.go:262
return nil, errors.New("tlv8: wrong size: " + value.Type().Name())
}
v = append(v, b[2:2+l]...)
b = b[2+l:]
// if size == 255 and same tag - continue read big payload
if l < 255 || len(b) < 2 || b[0] != t {
break
}
l = int(b[1])
}
tag := strconv.Itoa(int(t))
valueField, ok := getStructField(value, tag)
if !ok {
return b, fmt.Errorf("tlv8: can't find T=%d,L=%d,V=%x for: %s", t, l, v, value.Type().Name())
}
if err := unmarshalValue(v, valueField); err != nil {
return nil, err
}
return b, nil
}
func unmarshalSlice(b []byte, value reflect.Value) error {
valueIndex := value.Index(growSlice(value))
for len(b) > 0 {
var err error
if b, err = unmarshalTLV(b, valueIndex); err != nil {
if b != nil {
valueIndex = value.Index(growSlice(value))
continue
}View on GitHub (pinned to c245815e75)