Yalantis/uCrop · error · CImgIOException

save_tiff(): Failed to open file '%s' for writing.

Error message

save_tiff(): Failed to open file '%s' for writing.

What it means

After the null check, save_tiff() opens the file via TIFFOpen (libtiff) in "w4" or "w8" mode; if TIFFOpen returns NULL it throws CImgIOException that the file could not be opened for writing. This is an OS/libtiff-level open failure surfaced as a CImg exception.

Source

Thrown at ucrop/src/main/jni/CImg.h:62728

     **/
    const CImg<T>& save_tiff(const char *const filename, const unsigned int compression_type=0,
                             const float *const voxel_size=0, const char *const description=0,
                             const bool use_bigtiff=true) const {
      if (!filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_tiff(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty()) { cimg::fempty(0,filename); return *this; }

#ifdef cimg_use_tiff
      const bool
        _use_bigtiff = use_bigtiff && sizeof(ulongT)>=8 && size()*sizeof(T)>=1UL<<31; // No bigtiff for small images
      TIFF *tif = TIFFOpen(filename,_use_bigtiff?"w8":"w4");
      if (tif) {
        double val_min, val_max = (double)max_min(val_min);
        cimg_forZ(*this,z) _save_tiff(tif,z,z,compression_type,voxel_size,description,val_min,val_max);
        TIFFClose(tif);
      } else throw CImgIOException(_cimg_instance
                                   "save_tiff(): Failed to open file '%s' for writing.",
                                   cimg_instance,
                                   filename);
      return *this;
#else
      cimg::unused(compression_type,voxel_size,description,use_bigtiff);
      return save_other(filename);
#endif
    }

#ifdef cimg_use_tiff

#define _cimg_save_tiff(types,typed) if (!std::strcmp(types,pixel_type())) { \
    const typed foo = (typed)0; return _save_tiff(tif,directory,z,foo,compression_type,voxel_size,description,\
                                                  val_min,val_max); }

    // [internal] Save a plane into a tiff file.
    template<typename t>

View on GitHub (pinned to f788b534b4)

Solutions

  1. Create the output directory (mkdir -p equivalent) before saving
  2. Check file/path permissions and request storage permission on mobile
  3. Verify the filename is a valid, writable path
  4. Check free disk space
  5. Test TIFFOpen/TIFFOpen-style open separately to get the OS errno

Example fix

// before
img.save_tiff("/data/out/result.tif"); // dir may not exist
// after
std::system("mkdir -p /data/out"); // or std::filesystem::create_directories
img.save_tiff("/data/out/result.tif");
Defensive patterns

Strategy: try-catch

Validate before calling

std::filesystem::path p(outPath);
std::filesystem::create_directories(p.parent_path());
FILE *probe = fopen(outPath, "wb"); if (!probe) throw std::runtime_error("unwritable tiff path"); fclose(probe);

Type guard

bool canOpenForWrite(const char *p) { if (!p || !*p) return false; FILE *f = fopen(p, "wb"); if (!f) return false; fclose(f); return true; }

Try / catch

try { img.save_tiff(path.c_str(), comp); } catch (CImgIOException &e) { fprintf(stderr, "tiff open failed: %s\n", e.what()); }

Prevention

When it happens

Trigger: save_tiff() on a path in a non-existent directory; no write permission; disk full or I/O error; path too long or invalid characters; read-only filesystem (e.g. Android internal dir).

Common situations: Writing to /sdcard root on newer Android without permission; output directory never created; filename with typos; sandboxed app without storage permission.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08). Data as JSON: /api/errors/173a9e8d51a30260. Report an issue: GitHub.