DrKLO/Telegram · error · OpusDecoderException

Invalid channel count: {channelCount}

Error message

Invalid channel count: {channelCount}

What it means

Channel count is read from headerBytes[9] (& 0xFF). This decoder caps it at 8 because the per-stream mapping array (streamMap) is allocated as new byte[8] (OpusDecoder.java:113). Opus itself allows up to 255 channels via mapping family 1, but this extension's multistream wiring only supports up to 8.

Source

Thrown at TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoder.java:109

    int initializationDataSize = initializationData.size();
    if (initializationDataSize != 1 && initializationDataSize != 3) {
      throw new OpusDecoderException("Invalid initialization data size");
    }
    if (initializationDataSize == 3
        && (initializationData.get(1).length != 8 || initializationData.get(2).length != 8)) {
      throw new OpusDecoderException("Invalid pre-skip or seek pre-roll");
    }
    preSkipSamples = getPreSkipSamples(initializationData);
    seekPreRollSamples = getSeekPreRollSamples(initializationData);
    skipSamples = preSkipSamples;

    byte[] headerBytes = initializationData.get(0);
    if (headerBytes.length < 19) {
      throw new OpusDecoderException("Invalid header length");
    }
    channelCount = getChannelCount(headerBytes);
    if (channelCount > 8) {
      throw new OpusDecoderException("Invalid channel count: " + channelCount);
    }
    int gain = readSignedLittleEndian16(headerBytes, 16);

    byte[] streamMap = new byte[8];
    int numStreams;
    int numCoupled;
    if (headerBytes[18] == 0) { // Channel mapping
      // If there is no channel mapping, use the defaults.
      if (channelCount > 2) { // Maximum channel count with default layout.
        throw new OpusDecoderException("Invalid header, missing stream map");
      }
      numStreams = 1;
      numCoupled = (channelCount == 2) ? 1 : 0;
      streamMap[0] = 0;
      streamMap[1] = 1;
    } else {
      if (headerBytes.length < 21 + channelCount) {
        throw new OpusDecoderException("Invalid header length");

View on GitHub (pinned to 45ab8f4308)

Solutions

  1. Use Opus content with 8 or fewer channels (up to 7.1).
  2. If you need more channels, use a decoder whose native multistream wiring supports them.
  3. If the count looks like garbage, suspect a corrupt/wrong file rather than a real multichannel stream.
Defensive patterns

Strategy: validation

Validate before calling

int ch = format.initializationData.get(0)[9] & 0xFF;
if (ch < 1 || ch > 8) {
  throw new IllegalArgumentException("Opus channel count out of range (1..8): " + ch);
}
new OpusDecoder(NUM_BUFFERS, NUM_BUFFERS, initSize, format.initializationData, cryptoConfig, outputFloat);

Try / catch

try {
  new OpusDecoder(..., format.initializationData, cryptoConfig, outputFloat);
} catch (OpusDecoderException e) {
  if (e.getMessage().startsWith("Invalid channel count")) {
    // route to a decoder supporting >8 channels, or mark unsupported
  } else { throw e; }
}

Prevention

When it happens

Trigger: An Opus stream whose identification header reports more than 8 channels, or a corrupt header byte 9 producing a large value.

Common situations: Rare legitimate >8-channel Opus content routed to this decoder; corrupted headers where byte 9 is garbage; mis-detected codec feeding non-Opus bytes.

Related errors


AI-assisted analysis of DrKLO/Telegram@45ab8f4308 (2026-08-14). Data as JSON: /api/errors/d3681e0bb6041bda. Report an issue: GitHub.