pion/webrtc · error

%w: invalid family 2 mapping

Error message

%w: invalid family 2 mapping

What it means

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.

Source

Thrown at pkg/media/oggwriter/oggwriter.go:686

			return fmt.Errorf("%w: channel map entry is out of range", errInvalidChannelMap)
		}
	}

	return nil
}

func validateFamilySpecificChannelMapping(
	family uint8,
	streamCount uint8,
	coupledCount uint8,
	mapping []byte,
) error {
	switch family {
	case channelMappingFamily1:
		return validateVorbisChannelMapping(streamCount, coupledCount, mapping)
	case channelMappingFamily2:
		if len(mapping) != 1 || streamCount != 1 || coupledCount != 0 || mapping[0] != 0 {
			return fmt.Errorf("%w: invalid family 2 mapping", errInvalidChannelMap)
		}
	}

	return nil
}

func validateVorbisChannelMapping(streamCount, coupledCount uint8, mapping []byte) error {
	var wantStreams, wantCoupled uint8
	var wantMapping []byte
	switch len(mapping) {
	case 1:
		wantStreams = 1
		wantCoupled = 0
		wantMapping = []byte{0}
	case 2:
		wantStreams = 1
		wantCoupled = 1
		wantMapping = []byte{0, 1}

View on GitHub (pinned to 8c25dc09fa)

Solutions

  1. If you meant stereo, use family 0 with streamCount=1, coupledCount=1, mapping {0,1}.
  2. For family 2, send exactly: streamCount=1, coupledCount=0, mapping=[]byte{0}.
  3. Drop the custom mapping and let defaultChannelMapping configure mono/stereo.
  4. Compare with errors.Is(err, errInvalidChannelMap) to identify mapping misconfigurations.

Example fix

// before
validateChannelMapping(channelMappingFamily2, 1, 1, []byte{0, 1})
// after
validateChannelMapping(channelMappingFamily2, 1, 0, []byte{0})
Defensive patterns

Strategy: validation

Validate before calling

func validFamily2(streams, coupled uint8, mapping []byte) bool {
    return len(mapping) == 1 && streams == 1 && coupled == 0 && mapping[0] == 0
}

Type guard

func isFamily2Compliant(m ChannelMapping) bool {
    return m.Family == 2 && m.StreamCount == 1 && m.CoupledCount == 0 && len(m.Mapping) == 1 && m.Mapping[0] == 0
}

Try / catch

if err := writer.AddOpusTrack(cfg); err != nil {
    if errors.Is(err, errInvalidChannelMap) { /* family 2 requires 1/0/{0} */ }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of pion/webrtc@8c25dc09fa (2026-09-03). Data as JSON: /api/errors/c767d6e6a8e35dbe. Report an issue: GitHub.