pion/webrtc · error

%w: invalid family 1 mapping

Error message

%w: invalid family 1 mapping

What it means

For mapping family 1, once the mapping length (1 or 2) is recognized, the stream count, coupled count, and mapping bytes must exactly match the canonical Vorbis mono ({0}: 1/0) or stereo ({0,1}: 1/1) tables. Any other combination returns this error, wrapped around errInvalidChannelMap.

Source

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

}

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}
	default:
		return fmt.Errorf("%w: unsupported family 1 channel count", errInvalidChannelMap)
	}
	if streamCount != wantStreams || coupledCount != wantCoupled || !bytes.Equal(mapping, wantMapping) {
		return fmt.Errorf("%w: invalid family 1 mapping", errInvalidChannelMap)
	}

	return nil
}

func cloneChannelMapping(mapping channelMapping) channelMapping {
	mapping.mapping = append([]byte(nil), mapping.mapping...)

	return mapping
}

func defaultOpusTags() OpusTags {
	return OpusTags{Vendor: defaultVendor}
}

func cloneOpusTags(opusTags OpusTags) OpusTags {
	opusTags.UserComments = cloneUserComments(opusTags.UserComments)

View on GitHub (pinned to 8c25dc09fa)

Solutions

  1. Use the exact canonical tables: mono -> streams=1, coupled=0, {0}; stereo -> streams=1, coupled=1, {0,1}.
  2. Compare your table with bytes.Equal against the canonical mapping to spot ordering issues.
  3. Prefer defaultChannelMapping(channelCount) instead of a custom family-1 mapping.
  4. Handle via errors.Is(err, errInvalidChannelMap) in caller diagnostics.

Example fix

// before
validateChannelMapping(channelMappingFamily1, 1, 0, []byte{0, 1}) // mono counts, stereo table
// after
validateChannelMapping(channelMappingFamily1, 1, 1, []byte{0, 1})
Defensive patterns

Strategy: validation

Validate before calling

var canonical = map[int]struct{ s, c uint8; m []byte }{
    1: {1, 0, []byte{0}},
    2: {1, 1, []byte{0, 1}},
}
func matchesCanonical(n int, s, c uint8, m []byte) bool {
    w, ok := canonical[n]; return ok && s == w.s && c == w.c && bytes.Equal(m, w.m)
}

Type guard

func isCanonicalFamily1(s, c uint8, m []byte) bool {
    if len(m) == 1 { return s == 1 && c == 0 && m[0] == 0 }
    if len(m) == 2 { return s == 1 && c == 1 && m[0] == 0 && m[1] == 1 }
    return false
}

Try / catch

if err := validateChannelMapping(family, s, c, m); err != nil {
    if errors.Is(err, errInvalidChannelMap) { /* compare against canonical {0}/{0,1} tables */ }
    return err
}

Prevention

When it happens

Trigger: Passing family=channelMappingFamily1 with len(mapping)==1 or 2 but inconsistent streamCount/coupledCount/mapping bytes, e.g. streamCount=1, coupledCount=0, mapping []byte{0,1}, or mapping []byte{1,0}.

Common situations: Swapping coupledCount with the number of channels; reordering the mapping entries (e.g. channel-swap tables); typos when hand-rolling the mapping instead of using defaults.

Related errors


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