{"record":{"id":"08f3c4c1d0408eac","repo":"DrKLO/Telegram","slug":"invalid-header-missing-stream-map","errorCode":null,"errorMessage":"Invalid header, missing stream map","messagePattern":"Invalid header, missing stream map","errorType":"exception","errorClass":"OpusDecoderException","httpStatus":null,"severity":"error","filePath":"TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoder.java","lineNumber":119,"sourceCode":"    skipSamples = preSkipSamples;\n\n    byte[] headerBytes = initializationData.get(0);\n    if (headerBytes.length < 19) {\n      throw new OpusDecoderException(\"Invalid header length\");\n    }\n    channelCount = getChannelCount(headerBytes);\n    if (channelCount > 8) {\n      throw new OpusDecoderException(\"Invalid channel count: \" + channelCount);\n    }\n    int gain = readSignedLittleEndian16(headerBytes, 16);\n\n    byte[] streamMap = new byte[8];\n    int numStreams;\n    int numCoupled;\n    if (headerBytes[18] == 0) { // Channel mapping\n      // If there is no channel mapping, use the defaults.\n      if (channelCount > 2) { // Maximum channel count with default layout.\n        throw new OpusDecoderException(\"Invalid header, missing stream map\");\n      }\n      numStreams = 1;\n      numCoupled = (channelCount == 2) ? 1 : 0;\n      streamMap[0] = 0;\n      streamMap[1] = 1;\n    } else {\n      if (headerBytes.length < 21 + channelCount) {\n        throw new OpusDecoderException(\"Invalid header length\");\n      }\n      // Read the channel mapping.\n      numStreams = headerBytes[19] & 0xFF;\n      numCoupled = headerBytes[20] & 0xFF;\n      System.arraycopy(headerBytes, 21, streamMap, 0, channelCount);\n    }\n    nativeDecoderContext =\n        opusInit(SAMPLE_RATE, channelCount, numStreams, numCoupled, gain, streamMap);\n    if (nativeDecoderContext == 0) {\n      throw new OpusDecoderException(\"Failed to initialize decoder\");","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/DrKLO/Telegram/blob/45ab8f4308496e1f01026a97fcdb0d58a5274474/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoder.java#L101-L137","documentation":"Channel mapping family 0 (headerBytes[18] == 0) is the default mono/stereo layout and only supports 1 or 2 channels. The decoder takes the default-mapping branch only for <= 2 channels; if the header declares family 0 but channelCount > 2 it is internally inconsistent and rejected as missing a stream map.","triggerScenarios":"An Opus identification header that sets channel mapping family to 0 while simultaneously reporting more than 2 channels - a malformed or hand-authored header.","commonSituations":"Corrupt Opus files; test fixtures with an inconsistent header; a muxer that wrote family 0 for multichannel audio by mistake.","solutions":["Use a properly mapped multichannel Opus stream (channel mapping family 1, which carries an explicit stream map).","For mono/stereo content, keep channelCount <= 2 with mapping family 0."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"byte[] header = format.initializationData.get(0);\nint mappingFamily = header[18] & 0xFF;\nint ch = header[9] & 0xFF;\nif (mappingFamily == 0 && ch > 2) {\n  throw new IllegalArgumentException(\n      \"Opus mapping family 0 supports only mono/stereo, got \" + ch + \" channels\");\n}\nnew OpusDecoder(NUM_BUFFERS, NUM_BUFFERS, initSize, format.initializationData, cryptoConfig, outputFloat);","typeGuard":null,"tryCatchPattern":"try {\n  new OpusDecoder(..., format.initializationData, cryptoConfig, outputFloat);\n} catch (OpusDecoderException e) {\n  if (e.getMessage().contains(\"missing stream map\")) {\n    // use mapping family 1 content, or mono/stereo\n  } else { throw e; }\n}","preventionTips":["For >2 channel Opus, use channel mapping family 1 (with an explicit stream map).","Validate mapping-family/channel-count consistency before decoding."],"tags":["opus","decoder","format-validation","exoplayer","audio"],"backgroundTag":null,"analyzedSha":"45ab8f4308496e1f01026a97fcdb0d58a5274474","analyzedAt":"2026-08-14T05:19:30.815Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}