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
- Ensure the payload passed to ParseOpusHead is at least 19 bytes
- Check len(payload) before calling ParseOpusHead
- 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
- Keep OpusHead payloads intact end-to-end; do not slice packets arbitrarily
- Validate len(payload) at the network boundary before parsing
- Build test fixtures from real encoder output, not hand-typed bytes
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
- wrong header, expected beginning of stream
- invalid channel count
- %w: stream count must be one
- %w: coupled count exceeds stream count
- %w: channel map entry is out of range
AI-assisted analysis of pion/webrtc@8c25dc09fa (2026-09-03).
Data as JSON: /api/errors/c47fd37ec5c90f8b.
Report an issue: GitHub.