pion/webrtc · error

bad header signature

Error message

bad header signature

What it means

errBadIDPageSignature is returned when the first Ogg page header does not begin with the required 4-byte 'OggS' capture signature. The reader validates the ID page header via validateOpusPageHeader and rejects anything that is not a valid Ogg stream start. It means the input is not a well-formed Ogg file (or the stream is misaligned).

Source

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

import (
	"encoding/binary"
	"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.

View on GitHub (pinned to 8c25dc09fa)

Solutions

  1. Verify the input actually starts with the 'OggS' magic bytes before parsing
  2. Open the correct file / seek to offset 0 of the Ogg stream
  3. Check the caller that produced the byte slice for off-by-one or header-stripping bugs
  4. Use a tool (ogginfo) to confirm the file integrity; regenerate if corrupt

Example fix

// before
f, _ := os.Open("audio.opus") // actually raw opus, no ogg container
_, _, err := oggreader.NewWith(f) // errBadIDPageSignature
// after
// mux raw opus into an ogg container first, then:
f, _ := os.Open("audio.ogg")
_, _, err := oggreader.NewWith(f)
Defensive patterns

Strategy: validation

Validate before calling

sig := make([]byte, 4)
if _, err := io.ReadFull(f, sig); err != nil || string(sig) != "OggS" {
    return errors.New("input is not an Ogg stream")
}
// rewind, then: oggreader.NewWith(io.MultiReader(bytes.NewReader(sig), f))

Type guard

func isOggStream(b []byte) bool { return len(b) >= 4 && string(b[:4]) == "OggS" }

Try / catch

_, _, err := oggreader.NewWith(f)
if err != nil {
    if errors.Is(err, oggreader.ErrBadIDPageSignature) { // sentinel as exported by the package
        return fmt.Errorf("not a valid Ogg file: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Passing a non-Ogg file (raw Opus, WAV, MP3) to oggreader; reading a stream offset from byte 0 (e.g. after seeking); a truncated/corrupt file whose first bytes were overwritten.

Common situations: Wrong file extension vs actual content, concatenated or partially downloaded files, reading from the middle of a container, test fixtures with intentionally corrupted headers.

Related errors


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