pion/webrtc · error

%w: payload too short

Error message

%w: payload too short

What it means

validateOpusTagsHeader returns this error when the payload handed to oggreader.ParseOpusTags is shorter than the minimum required OpusTags header length. The parser must read at least the 8-byte 'OpusTags' magic plus the vendor length field, so a truncated buffer cannot possibly be a valid tags header. The sentinel errBadOpusTagsSignature is wrapped so callers can match with errors.Is.

Source

Thrown at pkg/media/oggreader/oggreader.go:413

	vendor, vendorEnd, err := parseVendorString(payload, headerMagicLen, u32Size, minHeaderLen)
	if err != nil {
		return nil, err
	}

	userComments, err := parseUserComments(payload, vendorEnd, u32Size)
	if err != nil {
		return nil, err
	}

	return &OpusTags{
		Vendor:       vendor,
		UserComments: userComments,
	}, nil
}

func validateOpusTagsHeader(payload []byte, minHeaderLen int) error {
	if len(payload) < minHeaderLen {
		return fmt.Errorf("%w: payload too short", errBadOpusTagsSignature)
	}

	got := HeaderType(payload[:8])
	if got != HeaderOpusTags {
		return fmt.Errorf("%w: expected %q, got %q", errBadOpusTagsSignature, HeaderOpusTags, got)
	}

	return nil
}

func parseVendorString(payload []byte, headerMagicLen, u32Size, minHeaderLen int) (string, int, error) {
	vendorLen32 := binary.LittleEndian.Uint32(payload[headerMagicLen : headerMagicLen+u32Size])
	if int(vendorLen32) > len(payload)-minHeaderLen {
		return "", 0, fmt.Errorf("%w: payload too short for vendor string", errBadOpusTagsSignature)
	}
	vendorLen := int(vendorLen32)

	vendorStart := headerMagicLen + u32Size

View on GitHub (pinned to 8c25dc09fa)

Solutions

  1. Verify the packet is the real OpusTags packet (starts with 'OpusTags') and pass the complete payload, not a truncated slice.
  2. Check that the Ogg page was fully reassembled before parsing; handle logical-stream segmentation so payload length is not cut.
  3. Guard at the call site with len(payload) >= 12 and errors.Is(err, ErrBadOpusTagsSignature) to skip non-tags packets.

Example fix

// before
header, err := oggreader.ParseOpusTags(packet[:7]) // truncated slice
// after
if len(packet) >= 12 {
    header, err = oggreader.ParseOpusTags(packet)
}
Defensive patterns

Strategy: validation

Validate before calling

const minOpusTagsLen = 12 // "OpusTags" magic + 4-byte vendor length
if len(payload) >= minOpusTagsLen && string(payload[:8]) == "OpusTags" {
    tags, err := oggreader.ParseOpusTags(payload)
}

Type guard

func isPlausibleOpusTags(p []byte) bool {
    return len(p) >= 12 && string(p[:8]) == "OpusTags"
}

Try / catch

tags, err := oggreader.ParseOpusTags(payload)
if errors.Is(err, oggreader.ErrBadOpusTagsSignature) {
    // treat packet as non-tags / truncated; skip or reassemble
} else if err != nil {
    return err
}

Prevention

When it happens

Trigger: Calling ParseOpusTags with a payload shorter than the minHeaderLen computed for it (e.g. fewer than ~12 bytes, magic + 4-byte vendor length); passing a packet slice cut short by a truncated Ogg page or an off-by-one range.

Common situations: Truncated/corrupt downloads of .opus files; slicing a reassembled Ogg stream incorrectly (dropping trailing bytes); parsing a comment header captured with a fixed-size buffer smaller than the actual header; treating a random packet (audio or ID header) as the tags packet.

Related errors


AI-assisted analysis of pion/webrtc@8c25dc09fa (2026-09-03). Data as JSON: /api/errors/acd96eabd17aa516. Report an issue: GitHub.