AlexxIT/go2rtc · error
tlv8: unmarshal zero data
Error message
tlv8: unmarshal zero data
What it means
tlv8.Unmarshal rejects empty input: TLV8 data must contain at least one tag/length/value record, so len(data)==0 is treated as a decoding error rather than leaving the target zero-valued. It protects callers from silently treating an empty body as a valid message.
Solutions
- Check len(data) (or the decoded base64 string) is non-zero before calling Unmarshal and treat empty as a protocol/transport-level problem.
- Inspect why the producer sent zero bytes: truncated read, empty request body, or upstream error — fix at the source.
- If an empty payload is legitimately meaningful in your protocol, guard it in caller code instead of routing it through Unmarshal.
- For UnmarshalReader, verify Content-Length > 0 or that io.ReadAll returned data before decoding.
Example fix
// before
var msg message
if err := tlv8.UnmarshalBase64(req.EncryptedData, &msg); err != nil { return err } // fails on ""
// after
if req.EncryptedData == "" {
return errors.New("empty tlv8 payload from peer")
}
var msg message
if err := tlv8.UnmarshalBase64(req.EncryptedData, &msg); err != nil { return err } Defensive patterns
Strategy: validation
Validate before calling
func safeUnmarshal(data []byte, v any) error {
if len(data) == 0 {
return errors.New("peer sent empty tlv8 payload")
}
return tlv8.Unmarshal(data, v)
} Try / catch
if err := tlv8.UnmarshalReader(req.Body, req.ContentLength, &msg); err != nil {
if strings.Contains(err.Error(), "zero data") {
return errors.New("empty TLV8 body from peer; check request format")
}
return err
} Prevention
- Check len(data)/Content-Length > 0 before decoding TLV8 bodies.
- Handle empty peer payloads as transport errors, not decode retries.
- When decoding persisted base64 fields, treat empty strings as absent data.
When it happens
Trigger: Calling tlv8.Unmarshal(nil, &v), tlv8.Unmarshal([]byte{}, &v), or via UnmarshalBase64 with an empty/whitespace-only string, or UnmarshalReader when the reader yields zero bytes (e.g. HTTP request with Content-Length 0 or an empty body).
Common situations: Peer sent an empty HTTP body with a TLV8 content type; reading a truncated response; decoding an empty base64 field from persisted state; off-by-one slicing that produced an empty slice; a client sending a keep-alive/empty POST that the server tries to decode.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- tlv8: zero item
- tlv8: value should be pointer:
- tlv8: wrong size:
- tlv8: can't find T= ,L= ,V= for
- rtmp: unknown command:
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/2f317906d050800c.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/hap/tlv8/tlv8.go:196
var data []byte
var err error
if n > 0 {
data = make([]byte, n)
_, err = io.ReadFull(r, data)
} else {
data, err = io.ReadAll(r)
}
if err != nil {
return err
}
return Unmarshal(data, v)
}
func Unmarshal(data []byte, v any) error {
if len(data) == 0 {
return errors.New("tlv8: unmarshal zero data")
}
value := reflect.ValueOf(v)
kind := value.Kind()
if kind != reflect.Pointer {
return errors.New("tlv8: value should be pointer: " + kind.String())
}
value = value.Elem()
kind = value.Kind()
if kind == reflect.Interface {
value = value.Elem()
kind = value.Kind()
}
switch kind {View on GitHub (pinned to c245815e75)