pion/webrtc · error
%w: expected %q, got %q
Error message
%w: expected %q, got %q
What it means
validateOpusTagsHeader rejects a payload whose first 8 bytes are not the 'OpusTags' magic string. ParseOpusTags only parses Opus comment headers, so any other header type (e.g. 'OpusHead') or garbage bytes trigger this wrapped errBadOpusTagsSignature error, reporting expected vs received magic.
Source
Thrown at pkg/media/oggreader/oggreader.go:418
userComments, err := parseUserComments(payload, vendorEnd, u32Size)
if err != nil {
return nil, err
}
return &OpusTags{
Vendor: vendor,
UserComments: userComments,
}, nil
}
func validateOpusTagsHeader(payload []byte, minHeaderLen int) error {
if len(payload) < minHeaderLen {
return fmt.Errorf("%w: payload too short", errBadOpusTagsSignature)
}
got := HeaderType(payload[:8])
if got != HeaderOpusTags {
return fmt.Errorf("%w: expected %q, got %q", errBadOpusTagsSignature, HeaderOpusTags, got)
}
return nil
}
func parseVendorString(payload []byte, headerMagicLen, u32Size, minHeaderLen int) (string, int, error) {
vendorLen32 := binary.LittleEndian.Uint32(payload[headerMagicLen : headerMagicLen+u32Size])
if int(vendorLen32) > len(payload)-minHeaderLen {
return "", 0, fmt.Errorf("%w: payload too short for vendor string", errBadOpusTagsSignature)
}
vendorLen := int(vendorLen32)
vendorStart := headerMagicLen + u32Size
vendorEnd := vendorStart + vendorLen
if vendorEnd+u32Size > len(payload) {
return "", 0, fmt.Errorf("%w: payload too short for vendor+comment count", errBadOpusTagsSignature)
}
View on GitHub (pinned to 8c25dc09fa)
Solutions
- Identify the correct packet: check bytes.HasPrefix(payload, []byte("OpusTags")) before calling ParseOpusTags and route 'OpusHead' packets to ParseOpusHead instead.
- Re-scan the stream to locate the actual OpusTags packet (usually the second packet of the first logical stream).
- Handle errors.Is(err, ErrBadOpusTagsSignature) at the call site and skip non-tags packets rather than aborting.
Example fix
// before
tags, err := oggreader.ParseOpusTags(packet) // may be OpusHead packet
// after
if bytes.HasPrefix(packet, []byte("OpusTags")) {
tags, err = oggreader.ParseOpusTags(packet)
} Defensive patterns
Strategy: type-guard
Validate before calling
if bytes.HasPrefix(payload, []byte("OpusTags")) {
tags, err := oggreader.ParseOpusTags(payload)
} else if bytes.HasPrefix(payload, []byte("OpusHead")) {
head, err := oggreader.ParseOpusHead(payload)
} Type guard
func isOpusTagsPacket(p []byte) bool {
return len(p) >= 8 && string(p[:8]) == "OpusTags"
} Try / catch
tags, err := oggreader.ParseOpusTags(payload)
var sigErr *? // sentinel-based check:
if errors.Is(err, oggreader.ErrBadOpusTagsSignature) {
// wrong packet type: route to ParseOpusHead or skip
} Prevention
- Track packet index per logical stream: parse tags only for the OpusTags (usually second) packet.
- Dispatch on the 8-byte magic before calling any parser.
- Handle streams starting mid-file by scanning forward for the OpusTags magic.
- Log the received HeaderType from the error message to diagnose misrouted packets.
When it happens
Trigger: Calling ParseOpusTags on the OpusHead (identification) packet, on an audio data packet, or on any non-comment-header packet; byte offsets misaligned so payload[:8] is not the magic.
Common situations: Iterating an Ogg stream and feeding every packet to ParseOpusTags instead of only the second logical-stream packet; stream starts mid-file so the ID header was missed and packets are misidentified; corrupted first 8 bytes of the tags packet.
Related errors
- bad opus tags signature
- %w: ambisonics family type 3 is not supported
- %w: payload too short
- %w: payload too short for vendor string
- %w: payload too short for vendor+comment count
AI-assisted analysis of pion/webrtc@8c25dc09fa (2026-09-03).
Data as JSON: /api/errors/6bafad2844f6ec49.
Report an issue: GitHub.