{"record":{"id":"b50607fa7b259509","repo":"pion/webrtc","slug":"bad-opus-tags-signature","errorCode":null,"errorMessage":"bad opus tags signature","messagePattern":"bad opus tags signature","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/media/oggreader/oggreader.go","lineNumber":26,"sourceCode":"\t\"encoding/binary\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"strings\"\n)\n\nconst (\n\tpageHeaderTypeBeginningOfStream = 0x02\n\tpageHeaderSignature             = \"OggS\"\n\n\tidPageBasePayloadLength = 19\n\tpageHeaderLen           = 27\n)\n\nvar (\n\terrNilStream                       = errors.New(\"stream is nil\")\n\terrBadIDPageSignature              = errors.New(\"bad header signature\")\n\terrBadOpusTagsSignature            = errors.New(\"bad opus tags signature\")\n\terrBadIDPageType                   = errors.New(\"wrong header, expected beginning of stream\")\n\terrBadIDPageLength                 = errors.New(\"payload for id page must be 19 bytes\")\n\terrBadIDPagePayloadSignature       = errors.New(\"bad payload signature\")\n\terrShortPageHeader                 = errors.New(\"not enough data for payload header\")\n\terrChecksumMismatch                = errors.New(\"expected and actual checksum do not match\")\n\terrUnsupportedChannelMappingFamily = errors.New(\"unsupported channel mapping family\")\n)\n\n// OggReader is used to read Ogg files and return page payloads.\ntype OggReader struct {\n\tstream               io.Reader\n\tbytesReadSuccesfully int64\n\tchecksumTable        *[256]uint32\n\tdoChecksum           bool\n}\n\n// OggHeader contains Opus codec metadata parsed from an Opus ID page.\n// This header is extracted from an Ogg page payload that starts with the OpusHead","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/pion/webrtc/blob/8c25dc09fa9e7c09aac4309ead88093d760432b0/pkg/media/oggreader/oggreader.go#L8-L44","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nif err := validateOpusTagsHeader(payload[:4], 8); err != nil { ... } // payload too short\n// after\nif len(payload) < 8 || HeaderType(payload[:8]) != HeaderOpusTags {\n    return fmt.Errorf(\"not an OpusTags payload\")\n}\nif err := validateOpusTagsHeader(payload, 8); err != nil { ... }","handlingStrategy":"try-catch","validationCode":"if len(payload) < 8 || HeaderType(payload[:8]) != HeaderOpusTags {\n    return errors.New(\"second ogg page is not OpusTags\")\n}","typeGuard":"func isOpusTagsPayload(p []byte) bool {\n    return len(p) >= 8 && HeaderType(p[:8]) == HeaderOpusTags\n}","tryCatchPattern":"err := validateOpusTagsHeader(payload, minLen)\nif err != nil {\n    if errors.Is(err, oggreader.ErrBadOpusTagsSignature) { // sentinel as exported by the package\n        return fmt.Errorf(\"malformed OpusTags header: %w\", err)\n    }\n    return err\n}","preventionTips":["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"],"tags":["go","media","ogg","opus","corrupt-file"],"backgroundTag":"bad-file-signature","analyzedSha":"8c25dc09fa9e7c09aac4309ead88093d760432b0","analyzedAt":"2026-09-03T21:56:56.182Z","contentChangedAt":"2026-09-03T21:56:56.182Z","schemaVersion":2},"datasetVersion":"2026-09-11T07:07:21.782Z"}