pion/webrtc · error
bad opus tags signature
Error message
bad opus tags signature
What it means
errBadOpusTagsSignature is returned when the OpusTags header (second Ogg page) does not carry the expected 8-byte 'OpusTags' header type, or when the payload is too short to contain it. It is wrapped with fmt.Errorf so extra context ('payload too short' or 'expected %q, got %q') accompanies the sentinel. It is produced by validateOpusTagsHeader and its helpers (parseVendorString, parseUserComments).
Source
Thrown at pkg/media/oggreader/oggreader.go:26
"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.
// This header is extracted from an Ogg page payload that starts with the OpusHeadView on GitHub (pinned to 8c25dc09fa)
Solutions
- Verify page 2 payload begins with 'OpusTags' before parsing
- Check the muxer that produced the file emits the OpusTags header page after OpusHead
- Ensure the full page payload was read (short reads cause 'payload too short')
- Handle the wrapped sentinel with errors.Is so the contextual message is preserved while matching
Example fix
// before
if err := validateOpusTagsHeader(payload[:4], 8); err != nil { ... } // payload too short
// after
if len(payload) < 8 || HeaderType(payload[:8]) != HeaderOpusTags {
return fmt.Errorf("not an OpusTags payload")
}
if err := validateOpusTagsHeader(payload, 8); err != nil { ... } Defensive patterns
Strategy: try-catch
Validate before calling
if len(payload) < 8 || HeaderType(payload[:8]) != HeaderOpusTags {
return errors.New("second ogg page is not OpusTags")
} Type guard
func isOpusTagsPayload(p []byte) bool {
return len(p) >= 8 && HeaderType(p[:8]) == HeaderOpusTags
} Try / catch
err := validateOpusTagsHeader(payload, minLen)
if err != nil {
if errors.Is(err, oggreader.ErrBadOpusTagsSignature) { // sentinel as exported by the package
return fmt.Errorf("malformed OpusTags header: %w", err)
}
return err
} Prevention
- Read complete Ogg pages before parsing their payloads
- Match sentinels with errors.Is, not string comparison, since the error is wrapped
- Verify the muxer emits OpusHead followed by OpusTags pages
- Fuzz/corruption-test parsers that ingest untrusted media
When it happens
Trigger: Parsing an Ogg stream whose second page payload is shorter than minHeaderLen; the first 8 bytes of the OpusTags payload are not HeaderOpusTags (e.g. 'OpusHead' repeated, or a corrupted page); calling validateOpusTagsHeader directly with malformed payload.
Common situations: Streams where pages were reordered or the metadata page was dropped, files muxed with a broken tool, manually truncated metadata pages, fuzzed/corrupt inputs in tests.
Related errors
- bad header signature
- invalid media timebase
- stream is nil
- %w: ambisonics family type 3 is not supported
- %w: payload too short
AI-assisted analysis of pion/webrtc@8c25dc09fa (2026-09-03).
Data as JSON: /api/errors/b50607fa7b259509.
Report an issue: GitHub.