DrKLO/Telegram · error

%s: can't write to %s

Error message

%s: can't write to %s

What it means

In JCP_MAX_COMPRESSION mode, jpegtran writes the output buffer via JFWRITE(fp, buffer, size) at jpegtran.c:667. If fewer than `size` bytes are written and ferror(fp) is true, a write error occurred on the output file. Unlike the open failure, this happens after successful compression. The error message names the input file path (argv[file_index]) rather than the output path.

Source

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

  jpeg_finish_compress(&dstinfo);

#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
  if (jpeg_c_int_param_supported(&dstinfo, JINT_COMPRESS_PROFILE) &&
      jpeg_c_get_int_param(&dstinfo, JINT_COMPRESS_PROFILE)
        == JCP_MAX_COMPRESSION) {
    size_t nbytes;
    
    unsigned char *buffer = outbuffer;
    unsigned long size = outsize;
    if (prefer_smallest && insize < size) {
      size = insize;
      buffer = inbuffer;
    }

    nbytes = JFWRITE(fp, buffer, size);
    if (nbytes < size && ferror(fp)) {
      if (file_index < argc)
        fprintf(stderr, "%s: can't write to %s\n", progname,
                argv[file_index]);
      else
        fprintf(stderr, "%s: can't write to stdout\n", progname);
    }
  }
#endif
    
  jpeg_destroy_compress(&dstinfo);
  (void)jpeg_finish_decompress(&srcinfo);
  jpeg_destroy_decompress(&srcinfo);

  /* Close output file, if we opened it */
  if (fp != stdout)
    fclose(fp);

#ifdef PROGRESS_REPORT
  end_progress_monitor((j_common_ptr)&dstinfo);
#endif

View on GitHub (pinned to 45ab8f4308)

Solutions

  1. Check available disk space before processing: ensure at least 2-3x the input file size is free
  2. Write output to internal storage first, then move to the final destination
  3. Handle the partial output file: delete it so stale data isn't used
  4. Avoid piping output to processes that may exit early

Example fix

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

// after
// check free space first
long free = get_available_bytes("/sdcard/");
if (free < input_size * 3) {
    fprintf(stderr, "insufficient disk space\n");
    return -1;
}
jpegtran input.jpg -outfile /sdcard/nearly_full/out.jpg
Defensive patterns

Strategy: validation

Validate before calling

// Check available disk space before processing
#include <sys/statvfs.h>
int check_disk_space(const char *output_dir, size_t min_bytes) {
    struct statvfs vfs;
    if (statvfs(output_dir, &vfs) != 0) return -1;
    unsigned long long avail = (unsigned long long)vfs.f_bavail * vfs.f_bsize;
    if (avail < min_bytes) {
        fprintf(stderr, "Insufficient disk space: have %llu, need %zu\n",
                avail, min_bytes);
        return -1;
    }
    return 0;
}
// Call: check_disk_space(dirname(output_path), input_size * 3);

Try / catch

// After jpegtran, verify output file was fully written
struct stat st;
if (stat(output_path, &st) != 0 || st.st_size == 0) {
    unlink(output_path); // remove partial output
    return -1;
}

Prevention

When it happens

Trigger: Disk fills up during the write. Quota exceeded mid-write. The output file is on a filesystem that becomes read-only (e.g. ext4 remounted ro on error). A broken pipe to a downstream process that closed early.

Common situations: Large JPEG output written to nearly-full storage. Android external storage that gets unmounted mid-write. Writing to a FUSE filesystem with a quota. The output is piped to a viewer that exits before jpegtran finishes.

Related errors


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