{"record":{"id":"24bbd835f933fa6b","repo":"pion/webrtc","slug":"duplicate-ogg-track-serial","errorCode":null,"errorMessage":"duplicate Ogg track serial","messagePattern":"duplicate Ogg track serial","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/media/oggwriter/oggwriter.go","lineNumber":52,"sourceCode":"\tchannelMappingFamily1              = 1\n\tchannelMappingFamily2              = 2\n\tchannelMappingFamily255            = 255\n\tidPageSignature                    = \"OpusHead\"\n\tcommentPageSignature               = \"OpusTags\"\n\tdefaultVendor                      = \"pion\"\n\tpageHeaderSignature                = \"OggS\"\n\tpageHeaderSize                     = 27\n\tmaxOggPageSegments                 = 255\n\tnoGranulePosition                  = ^uint64(0)\n\tmaxUint32Length                    = uint64(1<<32 - 1)\n)\n\nvar (\n\terrFileNotOpened        = errors.New(\"file not opened\")\n\terrOutputNotOpened      = errors.New(\"output not opened\")\n\terrInvalidNilPacket     = errors.New(\"invalid nil packet\")\n\terrDuplicateTrackSSRC   = errors.New(\"duplicate Ogg track SSRC\")\n\terrDuplicateTrackSerial = errors.New(\"duplicate Ogg track serial\")\n\terrTracksStarted        = errors.New(\"cannot add Ogg tracks after writing has started\")\n\terrPacketSSRCMismatch   = errors.New(\"RTP packet SSRC does not match Ogg track SSRC\")\n\terrInvalidOpusPacket    = errors.New(\"invalid Opus packet\")\n\terrInvalidChannelCount  = errors.New(\"invalid channel count\")\n\terrInvalidChannelMap    = errors.New(\"invalid channel mapping\")\n\terrInvalidOpusTags      = errors.New(\"invalid OpusTags\")\n)\n\ntype pageRewriter interface {\n\tio.Seeker\n\tio.WriterAt\n}\n\ntype writerConfig struct {\n\tsampleRate     uint32\n\tchannelMapping channelMapping\n\tpageRewriter   pageRewriter\n\topusTags       OpusTags","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/pion/webrtc/blob/8c25dc09fa9e7c09aac4309ead88093d760432b0/pkg/media/oggwriter/oggwriter.go#L34-L70","documentation":"errDuplicateTrackSerial is returned by NewTrack when the caller explicitly requests a granulepos/serial number (via WithSerial) that is already allocated to another track in the same Ogg writer. Ogg logical streams are identified by a unique 32-bit serial number, so two tracks sharing one serial would corrupt the container. The writer pre-registers its own serial allocation, so collisions can occur even with explicit serials.","triggerScenarios":"Calling writer.NewTrack(ssrc, WithSerial(n)) where serialInUse(n) is true — i.e. a previous track (or an internally allocated track) already holds serial n.","commonSituations":"Hard-coding serial constants in multiple NewTrack calls; reusing a serial after restarting track setup on a long-lived writer; copy-pasted test fixtures using the same WithSerial value for two tracks.","solutions":["Use a distinct WithSerial value for each track on the same writer","Omit WithSerial and let the writer allocate a serial via allocateSerial()","Ensure serials are unique across restarts by deriving them from a counter or random value"],"exampleFix":"// before\ntrack1, err := writer.NewTrack(1111, WithSerial(0x01020304))\ntrack2, err := writer.NewTrack(2222, WithSerial(0x01020304)) // duplicate\n// after\ntrack1, err := writer.NewTrack(1111, WithSerial(0x01020304))\ntrack2, err := writer.NewTrack(2222, WithSerial(0x05060708))","handlingStrategy":"validation","validationCode":"func serialFree(w *oggwriter.Writer, serial uint32) bool {\n    return serial != 0 && !usedSerials[serial] // track serials you've handed out\n}","typeGuard":null,"tryCatchPattern":"track, err := writer.NewTrack(ssrc, oggwriter.WithSerial(mySerial))\nif errors.Is(err, oggwriter.errDuplicateTrackSerial) {\n    track, err = writer.NewTrack(ssrc, nil) // fall back to auto serial\n}","preventionTips":["Omit WithSerial and let the writer auto-allocate","Keep a registry of used serials per writer","Never hard-code serial constants in shared fixtures","Derive serials from a monotonically increasing counter"],"tags":["ogg","rtp","media","duplicate-serial"],"backgroundTag":"duplicate-resource-identifier","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"}