DrKLO/Telegram · warning

opus_custom_decode() failed: %s\n

Error message

opus_custom_decode() failed: %s\n

What it means

opus_custom_decode(dec, data, len, out, frame_size) returned ret < 0 during the decode loop. The message prints opus_strerror(ret). This is a warning only — execution continues, so 'out' may contain stale/uninitialized samples that get written to the output and feed the RESYNTH RMSD calculation. The decode can also be called with NULL data to simulate packet loss.

Source

Thrown at TMessagesProj/jni/opus/celt/opus_custom_demo.c:172

            }
            data[i/8] ^= 1<<(7-(i%8));
         }
      }
      if (errors == 1)
         data[eid/8] ^= 1<<(7-(eid%8));
      else if (errors%2 == 1)
         data[rand()%8] ^= 1<<rand()%8;
#endif

#if 1 /* Set to zero to use the encoder's output instead */
      /* This is to simulate packet loss */
      if (argc==9 && rand()%1000<atoi(argv[argc-3]))
      /*if (errors && (errors%2==0))*/
         ret = opus_custom_decode(dec, NULL, len, out, frame_size);
      else
         ret = opus_custom_decode(dec, data, len, out, frame_size);
      if (ret < 0)
         fprintf(stderr, "opus_custom_decode() failed: %s\n", opus_strerror(ret));
#else
      for (i=0;i<ret*channels;i++)
         out[i] = in[i];
#endif
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
      for (i=0;i<ret*channels;i++)
      {
         rmsd += (in[i]-out[i])*1.0*(in[i]-out[i]);
         /*out[i] -= in[i];*/
      }
#endif
      count++;
      fwrite(out+skip*channels, sizeof(short), (ret-skip)*channels, fout);
      skip = 0;
   }
   PRINT_MIPS(stderr);

   opus_custom_encoder_destroy(enc);

View on GitHub (pinned to 45ab8f4308)

Solutions

  1. Ensure len is > 0 (encode succeeded) before decoding; skip the iteration otherwise.
  2. On ret < 0, skip writing 'out' to the output file and exclude this frame from the RMSD count.
  3. If using the bit-error simulation, keep corruption within tolerable limits or expect decode errors.
  4. Match frame_size exactly between encode and decode calls.

Example fix

// before
ret = opus_custom_decode(dec, data, len, out, frame_size);
if (ret < 0)
    fprintf(stderr, "opus_custom_decode() failed: %s\n", opus_strerror(ret));

// after: guard the len, and skip write/RMSD on failure
if (len <= 0) { /* nothing to decode this frame */ continue; }
ret = opus_custom_decode(dec, data, len, out, frame_size);
if (ret < 0) { fprintf(stderr, "opus_custom_decode() failed: %s\n", opus_strerror(ret)); continue; }
Defensive patterns

Strategy: validation

Validate before calling

// Only decode when encode produced a valid length; skip on failure.
if (len <= 0) { continue; }
ret = opus_custom_decode(dec, data, len, out, frame_size);
if (ret < 0) { fprintf(stderr, "opus_custom_decode() failed: %s\n", opus_strerror(ret)); continue; }

Prevention

When it happens

Trigger: ret is a negative OPUS_* code. Causes: len is 0 or negative (especially if the encode step failed but the loop continued), corrupted packet data (the optional bit-error simulation), or frame_size mismatch with the decoder. The packet-loss branch passes NULL as the data pointer, which the decoder handles as concealment — but a bad len there still errors.

Common situations: Encode failure (error 211) left len <= 0 and the loop did not skip, so decode gets an invalid length; bit-error simulation enabled (#if block) corrupting bytes; frame_size inconsistent between encode and decode; very aggressive packet-loss rate producing many concealment calls.

Related errors


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