pion/webrtc · error
wrong header, expected beginning of stream
Error message
wrong header, expected beginning of stream
What it means
errBadIDPageType is returned when the first Ogg page of an Opus stream is not marked as the beginning-of-stream page. The library requires the ID header page to have headerType 0x02, as mandated by the Opus-in-Ogg encapsulation spec. If the stream does not start with a proper ID page, parsing cannot proceed safely.
Source
Thrown at pkg/media/oggreader/oggreader.go:27
"errors"
"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 stream begins from byte 0 with the original ID header page (headerType 0x02)
- Re-record or re-mux the file so the Opus ID page is first (e.g. with ffmpeg/oggz)
- Verify you are not seeking or skipping bytes before handing the reader to NewWith/New
Example fix
// before: file starts mid-stream
f, _ := os.Open("trimmed.opus")
r, _ := oggreader.NewWith(f)
// after: remux so ID page is first
// ffmpeg -i trimmed.opus -c copy fixed.opus
f, _ := os.Open("fixed.opus")
r, _ := oggreader.NewWith(f) Defensive patterns
Strategy: validation
Validate before calling
// read the first page header yourself before handing off
hdr := make([]byte, 27)
if _, err := io.ReadFull(f, hdr); err != nil { return err }
if hdr[0] != 'O' || hdr[1] != 'g' || hdr[2] != 'g' || hdr[3] != 'S' { return errors.New("not ogg") }
if hdr[5]&0x02 == 0 { return errors.New("first page is not beginning-of-stream") }
f.Seek(0, io.SeekStart) Type guard
func isBeginningOfStreamPage(hdr [27]byte) bool {
return hdr[0] == 'O' && hdr[1] == 'g' && hdr[2] == 'g' && hdr[3] == 'S' && hdr[5]&0x02 != 0
} Try / catch
_, hdr, err := oggreader.NewWith(f)
if errors.Is(err, oggreader.ErrBadIDPageType) {
// remux/re-record: stream does not start with ID page
} Prevention
- Always feed the reader from the very first byte of the file
- Never seek past the ID header before constructing the reader
- Use oggz/ffmpeg to validate files recorded or trimmed by your pipeline
When it happens
Trigger: Calling NewWith/New on a stream whose first Ogg page header has headerType != 0x02 (validateOpusPageHeader at oggreader.go:209). Also triggered directly in tests that feed a malformed ID page.
Common situations: Joining a mid-stream Ogg capture (recording started after the ID page was written), trimming a file so the first page was removed, concatenating streams so the reader starts on a continuation page, or feeding the reader a non-Opus Ogg page.
Related errors
- payload for id page must be 19 bytes
- bad payload signature
- bad opus tags signature
- unsupported channel mapping family
- invalid channel count
AI-assisted analysis of pion/webrtc@8c25dc09fa (2026-09-03).
Data as JSON: /api/errors/46c105cb48706143.
Report an issue: GitHub.