DrKLO/Telegram · error

%s: can't open %s for writing

Error message

%s: can't open %s for writing

What it means

jpegtran opens the output file with fopen(outfilename, WRITE_BINARY) at jpegtran.c:613. If fopen returns NULL, the output path is invalid: the parent directory doesn't exist, the process lacks write permission, or the disk is full. The program exits before writing any output.

Source

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

                                                 &transformoption);
#else
  dst_coef_arrays = src_coef_arrays;
#endif

  /* Close input file, if we opened it.
   * Note: we assume that jpeg_read_coefficients consumed all input
   * until JPEG_REACHED_EOI, and that jpeg_finish_decompress will
   * only consume more while (!cinfo->inputctl->eoi_reached).
   * We cannot call jpeg_finish_decompress here since we still need the
   * virtual arrays allocated from the source object for processing.
   */
  if (fp != stdin)
    fclose(fp);

  /* Open the output file. */
  if (outfilename != NULL) {
    if ((fp = fopen(outfilename, WRITE_BINARY)) == NULL) {
      fprintf(stderr, "%s: can't open %s for writing\n", progname,
              outfilename);
      exit(EXIT_FAILURE);
    }
  } else {
    /* default output file is stdout */
    fp = write_stdout();
  }

  /* Adjust default compression parameters by re-parsing the options */
  file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE);

  /* Specify data destination for compression */
#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)
    jpeg_mem_dest(&dstinfo, &outbuffer, &outsize);
  else

View on GitHub (pinned to 45ab8f4308)

Solutions

  1. Ensure the parent directory exists: `mkdir -p $(dirname outpath)` before invoking
  2. Verify write permission: `access(dirname, W_OK) == 0`
  3. Use the app's internal storage (`getFilesDir()`) for output
  4. Check available disk space before writing large outputs

Example fix

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

// after
mkdir -p /sdcard/output
jpegtran input.jpg -outfile /sdcard/output/out.jpg
Defensive patterns

Strategy: validation

Validate before calling

// Validate output path writability before invoking jpegtran
int validate_output_path(const char *path) {
    char dir[4096];
    strncpy(dir, path, sizeof(dir)-1); dir[sizeof(dir)-1] = '\0';
    char *slash = strrchr(dir, '/');
    if (slash) *slash = '\0';
    else strcpy(dir, ".");
    if (access(dir, W_OK) != 0) {
        fprintf(stderr, "Output directory not writable: %s\n", dir);
        return -1;
    }
    // check available space (at least 2x input size)
    struct statvfs vfs;
    if (statvfs(dir, &vfs) == 0) {
        unsigned long long avail = (unsigned long long)vfs.f_bavail * vfs.f_bsize;
        if (avail < 1024*1024) return -1; // less than 1MB free
    }
    return 0;
}

Prevention

When it happens

Trigger: Output directory doesn't exist (e.g. /tmp/out/ when /tmp/out is missing). No write permission on the target directory (e.g. /system on Android). Disk full or quota exceeded. The output path is a directory, not a file.

Common situations: JNI caller passes an output path in a sandboxed directory that the native process can't write to. Output path to external storage on Android without WRITE_EXTERNAL_STORAGE permission. Path with a trailing slash interpreted as a directory.

Related errors


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