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
- Create the output directory (mkdir -p equivalent) before saving
- Check file/path permissions and request storage permission on mobile
- Verify the filename is a valid, writable path
- Check free disk space
- 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
- Create output directories before saving
- Request/check storage permissions on mobile platforms
- Test writability with a probe open
- Watch disk space for large TIFFs
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
- save_tiff(): Specified compression type (%u) is invalid (sho
- save_tiff(): Invalid strip writing when saving file '%s'.
- save_tiff(): Failed to open stream for file '%s'.
- cimg::fopen(): Failed to open file '%s' with mode '%s'.
- load_tiff(): Specified filename is (null).
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/173a9e8d51a30260.
Report an issue: GitHub.