{"record":{"id":"c767d6e6a8e35dbe","repo":"pion/webrtc","slug":"w-invalid-family-2-mapping","errorCode":null,"errorMessage":"%w: invalid family 2 mapping","messagePattern":"%w: invalid family 2 mapping","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/media/oggwriter/oggwriter.go","lineNumber":686,"sourceCode":"\t\t\treturn fmt.Errorf(\"%w: channel map entry is out of range\", errInvalidChannelMap)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc validateFamilySpecificChannelMapping(\n\tfamily uint8,\n\tstreamCount uint8,\n\tcoupledCount uint8,\n\tmapping []byte,\n) error {\n\tswitch family {\n\tcase channelMappingFamily1:\n\t\treturn validateVorbisChannelMapping(streamCount, coupledCount, mapping)\n\tcase channelMappingFamily2:\n\t\tif len(mapping) != 1 || streamCount != 1 || coupledCount != 0 || mapping[0] != 0 {\n\t\t\treturn fmt.Errorf(\"%w: invalid family 2 mapping\", errInvalidChannelMap)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc validateVorbisChannelMapping(streamCount, coupledCount uint8, mapping []byte) error {\n\tvar wantStreams, wantCoupled uint8\n\tvar wantMapping []byte\n\tswitch len(mapping) {\n\tcase 1:\n\t\twantStreams = 1\n\t\twantCoupled = 0\n\t\twantMapping = []byte{0}\n\tcase 2:\n\t\twantStreams = 1\n\t\twantCoupled = 1\n\t\twantMapping = []byte{0, 1}","sourceCodeStart":668,"sourceCodeEnd":704,"githubUrl":"https://github.com/pion/webrtc/blob/8c25dc09fa9e7c09aac4309ead88093d760432b0/pkg/media/oggwriter/oggwriter.go#L668-L704","documentation":"Channel mapping family 2 (non-diegetic channels, per the Opus spec) has exactly one legal configuration: one stream, zero coupled streams, and a single mapping entry of 0. validateFamilySpecificChannelMapping rejects any deviation from that exact tuple. The error wraps errInvalidChannelMap.","triggerScenarios":"Passing family=channelMappingFamily2 with any of: len(mapping) != 1, streamCount != 1, coupledCount != 0, or mapping[0] != 0 — e.g. family 2 with a stereo mapping table.","commonSituations":"Choosing family 2 because it sounds like 'stereo/surround' when family 0 or 1 was intended; carrying over a family-1 mapping table while switching the family constant.","solutions":["If you meant stereo, use family 0 with streamCount=1, coupledCount=1, mapping {0,1}.","For family 2, send exactly: streamCount=1, coupledCount=0, mapping=[]byte{0}.","Drop the custom mapping and let defaultChannelMapping configure mono/stereo.","Compare with errors.Is(err, errInvalidChannelMap) to identify mapping misconfigurations."],"exampleFix":"// before\nvalidateChannelMapping(channelMappingFamily2, 1, 1, []byte{0, 1})\n// after\nvalidateChannelMapping(channelMappingFamily2, 1, 0, []byte{0})","handlingStrategy":"validation","validationCode":"func validFamily2(streams, coupled uint8, mapping []byte) bool {\n    return len(mapping) == 1 && streams == 1 && coupled == 0 && mapping[0] == 0\n}","typeGuard":"func isFamily2Compliant(m ChannelMapping) bool {\n    return m.Family == 2 && m.StreamCount == 1 && m.CoupledCount == 0 && len(m.Mapping) == 1 && m.Mapping[0] == 0\n}","tryCatchPattern":"if err := writer.AddOpusTrack(cfg); err != nil {\n    if errors.Is(err, errInvalidChannelMap) { /* family 2 requires 1/0/{0} */ }\n    return err\n}","preventionTips":["Family 2 only allows the exact tuple (streams=1, coupled=0, mapping={0})","Use family 0 for ordinary mono/stereo instead","Don't reuse family-1 tables when switching family constants","Verify family constants against the Opus spec before use"],"tags":["go","ogg","opus","channel-mapping","validation"],"backgroundTag":"invalid-opus-channel-mapping","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"}