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

  1. Ensure the stream begins from byte 0 with the original ID header page (headerType 0x02)
  2. Re-record or re-mux the file so the Opus ID page is first (e.g. with ffmpeg/oggz)
  3. 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

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


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