DrKLO/Telegram · error

%s: can't read from %s

Error message

%s: can't read from %s

What it means

During the memsrc read-loop (JCP_MAX_COMPRESSION mode), jpegtran calls JFREAD to fill the input buffer at jpegtran.c:551. If the read returns fewer than INPUT_BUF_SIZE bytes and ferror(fp) is true, a read I/O error occurred on the input file. The error message names the input file path from argv[file_index].

Source

Thrown at TMessagesProj/jni/mozjpeg/jpegtran.c:554

  /* Specify data source for decompression */
  if (jpeg_c_int_param_supported(&dstinfo, JINT_COMPRESS_PROFILE) &&
      jpeg_c_get_int_param(&dstinfo, JINT_COMPRESS_PROFILE)
        == JCP_MAX_COMPRESSION)
    memsrc = TRUE; /* needed to revert to original */
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
  if (memsrc) {
    size_t nbytes;
    do {
      inbuffer = (unsigned char *)realloc(inbuffer, insize + INPUT_BUF_SIZE);
      if (inbuffer == NULL) {
        fprintf(stderr, "%s: memory allocation failure\n", progname);
        exit(EXIT_FAILURE);
      }
      nbytes = JFREAD(fp, &inbuffer[insize], INPUT_BUF_SIZE);
      if (nbytes < INPUT_BUF_SIZE && ferror(fp)) {
        if (file_index < argc)
          fprintf(stderr, "%s: can't read from %s\n", progname,
                  argv[file_index]);
        else
          fprintf(stderr, "%s: can't read from stdin\n", progname);
      }
      insize += (unsigned long)nbytes;
    } while (nbytes == INPUT_BUF_SIZE);
    jpeg_mem_src(&srcinfo, inbuffer, insize);
  } else
#endif
  jpeg_stdio_src(&srcinfo, fp);

  /* Enable saving of extra markers that we want to copy */
  jcopy_markers_setup(&srcinfo, copyoption);

  /* Read file header */
  (void)jpeg_read_header(&srcinfo, TRUE);

  /* Any space needed by a transform option must be requested before

View on GitHub (pinned to 45ab8f4308)

Solutions

  1. Copy the input JPEG to reliable internal storage before processing
  2. Verify file integrity with a checksum before invoking jpegtran
  3. Retry from a different copy of the file
  4. Check device health if the error is persistent

Example fix

// before
jpegtran /sdcard/photos/input.jpg -outfile out.jpg

// after
// copy to internal storage first
copy_file("/sdcard/photos/input.jpg", internal_tmp);
jpegtran internal_tmp -outfile out.jpg;
Defensive patterns

Strategy: validation

Validate before calling

// Copy input from unreliable storage to internal storage before processing
int stage_input_file(const char *src, const char *internal_dir, char *dst, size_t dst_len) {
    snprintf(dst, dst_len, "%s/jpegtran_input_%d.jpg", internal_dir, getpid());
    FILE *in = fopen(src, "rb");
    if (!in) return -1;
    FILE *out = fopen(dst, "wb");
    if (!out) { fclose(in); return -1; }
    char buf[8192]; size_t n;
    while ((n = fread(buf, 1, sizeof(buf), in)) > 0) {
        if (fwrite(buf, 1, n, out) != n) { fclose(in); fclose(out); return -1; }
    }
    int err = ferror(in);
    fclose(in); fclose(out);
    return err ? -1 : 0;
}

Prevention

When it happens

Trigger: Reading from a file on failing storage (bad sector, corrupted SD card). A truncated JPEG file that causes an I/O error mid-read. File on a network mount that drops the connection. Android external storage that is unmounted during processing.

Common situations: Processing a JPEG from removable storage (SD card, USB OTG). File on a FUSE mount that returns EIO. Concurrent unmount of the storage device. A partially-downloaded JPEG file on a bad cache.

Related errors


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