DrKLO/Telegram · warning

opus_custom_encode() failed: %s\n

Error message

opus_custom_encode() failed: %s\n

What it means

opus_custom_encode(enc, in, frame_size, data, bytes_per_packet) returned len <= 0 during the encoding loop. The message prints opus_strerror(len). Critically, this is a WARNING only — the code prints the error but does NOT break the loop or skip the subsequent decode, so it feeds a garbage/zero len to the decoder on failure.

Source

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

   if (argc>7)
   {
      complexity=atoi(argv[5]);
      opus_custom_encoder_ctl(enc,OPUS_SET_COMPLEXITY(complexity));
   }

   in = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16));
   out = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16));

   while (!feof(fin))
   {
      int ret;
      err = fread(in, sizeof(short), frame_size*channels, fin);
      if (feof(fin))
         break;
      len = opus_custom_encode(enc, in, frame_size, data, bytes_per_packet);
      if (len <= 0)
         fprintf (stderr, "opus_custom_encode() failed: %s\n", opus_strerror(len));

      /* This is for simulating bit errors */
#if 0
      int errors = 0;
      int eid = 0;
      /* This simulates random bit error */
      for (i=0;i<len*8;i++)
      {
         if (rand()%atoi(argv[8])==0)
         {
            if (i<64)
            {
               errors++;
               eid = i;
            }
            data[i/8] ^= 1<<(7-(i%8));
         }
      }

View on GitHub (pinned to 45ab8f4308)

Solutions

  1. Check fread's return count and break/skip the iteration if it's less than frame_size*channels (partial frame).
  2. On len <= 0, skip the decode step (continue) instead of feeding the bad length to the decoder.
  3. Validate frame_size is an allowed CELT size for the chosen mode/rate before the loop.
  4. Read opus_strerror(len) to distinguish OPUS_BAD_ARG from OPUS_BUFFER_TOO_SMALL.

Example fix

// before
len = opus_custom_encode(enc, in, frame_size, data, bytes_per_packet);
if (len <= 0)
    fprintf (stderr, "opus_custom_encode() failed: %s\n", opus_strerror(len));

// after: skip the rest of the loop body on encode failure
len = opus_custom_encode(enc, in, frame_size, data, bytes_per_packet);
if (len <= 0) {
    fprintf (stderr, "opus_custom_encode() failed: %s\n", opus_strerror(len));
    continue;
}
Defensive patterns

Strategy: validation

Validate before calling

// Skip frames where the read was short or encode failed.
err = fread(in, sizeof(short), frame_size*channels, fin);
if (err != (size_t)(frame_size*channels)) { /* short read: end of data */ break; }
len = opus_custom_encode(enc, in, frame_size, data, bytes_per_packet);
if (len <= 0) { fprintf(stderr, "opus_custom_encode() failed: %s\n", opus_strerror(len)); continue; }

Prevention

When it happens

Trigger: The encoder returns a negative OPUS_* error code (e.g. OPUS_BAD_ARG if frame_size is invalid for the mode, OPUS_INTERNAL_ERROR) or 0. The input buffer 'in' is filled by fread each iteration; an incomplete final read (short frame) can also feed bad data.

Common situations: frame_size not a valid CELT frame size for the mode; input PCM shorter than a full frame on the last iteration (fread returns fewer samples but the code only checks feof after the read); bytes_per_packet of 0 forcing zero-length output; corrupted input samples.

Related errors


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