pion/webrtc · error

payload for id page must be 19 bytes

Error message

payload for id page must be 19 bytes

What it means

errBadIDPageLength is returned when the Opus ID header payload is shorter than the required 19 bytes (idPageBasePayloadLength). The OpusHead structure is fixed-size up to the channel mapping section, so a shorter payload cannot be parsed. It is returned from ParseOpusHead, validateOpusPageHeader, and validatePayloadLength.

Source

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

	"fmt"
	"io"
	"strings"
)

const (
	pageHeaderTypeBeginningOfStream = 0x02
	pageHeaderSignature             = "OggS"

	idPageBasePayloadLength = 19
	pageHeaderLen           = 27
)

var (
	errNilStream                       = errors.New("stream is nil")
	errBadIDPageSignature              = errors.New("bad header signature")
	errBadOpusTagsSignature            = errors.New("bad opus tags signature")
	errBadIDPageType                   = errors.New("wrong header, expected beginning of stream")
	errBadIDPageLength                 = errors.New("payload for id page must be 19 bytes")
	errBadIDPagePayloadSignature       = errors.New("bad payload signature")
	errShortPageHeader                 = errors.New("not enough data for payload header")
	errChecksumMismatch                = errors.New("expected and actual checksum do not match")
	errUnsupportedChannelMappingFamily = errors.New("unsupported channel mapping family")
)

// OggReader is used to read Ogg files and return page payloads.
type OggReader struct {
	stream               io.Reader
	bytesReadSuccesfully int64
	checksumTable        *[256]uint32
	doChecksum           bool
}

// OggHeader contains Opus codec metadata parsed from an Opus ID page.
// This header is extracted from an Ogg page payload that starts with the OpusHead
// signature (the first page of an Opus stream in an Ogg container).
//

View on GitHub (pinned to 8c25dc09fa)

Solutions

  1. Ensure the payload passed to ParseOpusHead is at least 19 bytes
  2. Check len(payload) before calling ParseOpusHead
  3. If building packets yourself, include the full OpusHead: 'OpusHead' magic, version, channels, pre-skip, sample rate, gain, mapping family

Example fix

// before
head, err := oggreader.ParseOpusHead(payload[:10])
// after
if len(payload) < 19 {
    return fmt.Errorf("opus id payload too short: %d", len(payload))
}
head, err := oggreader.ParseOpusHead(payload)
Defensive patterns

Strategy: validation

Validate before calling

if payload == nil || len(payload) < 19 {
    return fmt.Errorf("opus id payload must be >= 19 bytes, got %d", len(payload))
}
head, err := oggreader.ParseOpusHead(payload)

Type guard

func isFullOpusHead(payload []byte) bool {
    return len(payload) >= 19 && bytes.HasPrefix(payload, []byte("OpusHead"))
}

Try / catch

head, err := oggreader.ParseOpusHead(payload)
if errors.Is(err, oggreader.ErrBadIDPageLength) {
    return fmt.Errorf("truncated OpusHead: %w", err)
}

Prevention

When it happens

Trigger: Passing a []byte payload of len < 19 to ParseOpusHead (oggreader.go:68), or an ID page whose payload is truncated (oggreader.go:213).

Common situations: Manually constructed OpusHead payloads missing bytes, packets truncated by a network/packetizer bug, hand-rolled test fixtures with incomplete ID headers.

Related errors


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