Yalantis/uCrop · error · CImgArgumentException
save_exr(): Specified filename is (null).
Error message
save_exr(): Specified filename is (null).
What it means
save_exr() validates its filename argument before touching OpenEXR and throws CImgArgumentException on a null C-string, printing the literal '(null)'. It is the standard null-check guard used by all CImg savers, raised before the volumetric-slice warning or any file I/O.
Source
Thrown at ucrop/src/main/jni/CImg.h:63119
voxel_size[0],voxel_size[1],voxel_size[2]);
err+=cimg_snprintf(header._data + err,128,"TYPE=%s\nCPU=%s\n",
inrtype,cimg::endianness()?"sun":"decm");
std::memset(header._data + err,'\n',252 - err);
std::memcpy(header._data + 252,"##}\n",4);
cimg::fwrite(header._data,256,nfile);
cimg_forXYZ(*this,x,y,z) cimg_forC(*this,c) cimg::fwrite(&((*this)(x,y,z,c)),1,nfile);
if (!file) cimg::fclose(nfile);
return *this;
}
//! Save image as an OpenEXR file.
/**
\param filename Filename, as a C-string.
\note The OpenEXR file format is <a href="http://en.wikipedia.org/wiki/OpenEXR">described here</a>.
**/
const CImg<T>& save_exr(const char *const filename) const {
if (!filename)
throw CImgArgumentException(_cimg_instance
"save_exr(): Specified filename is (null).",
cimg_instance);
if (is_empty()) { cimg::fempty(0,filename); return *this; }
if (_depth>1)
cimg::warn(_cimg_instance
"save_exr(): Instance is volumetric, only the first slice will be saved in file '%s'.",
cimg_instance,
filename);
#ifndef cimg_use_openexr
return save_other(filename);
#else
Imf::Rgba *const ptrd0 = new Imf::Rgba[(size_t)_width*_height], *ptrd = ptrd0, rgba;
switch (_spectrum) {
case 1 : { // Grayscale image
for (const T *ptr_r = data(), *const ptr_e = ptr_r + (ulongT)_width*_height; ptr_r<ptr_e;) {
rgba.r = (half)(*(ptr_r));
rgba.g = (half)(*(ptr_r));View on GitHub (pinned to f788b534b4)
Solutions
- Check the filename for null/empty before the call and raise a clear error identifying the missing path source.
- Fix the upstream path producer (env var, config key, argument parsing) so it yields a valid string.
- If holding an open stream is more natural, use a writer overload accepting FILE* if available for your format, or open the file yourself first.
- Centralize filename validation in a save helper so all export paths get the same guard.
Example fix
// before
const char *out = getenv("EXR_PATH");
img.save_exr(out); // throws when EXR_PATH unset
// after
const char *out = getenv("EXR_PATH");
if (!out || !*out) throw std::runtime_error("EXR_PATH is required");
img.save_exr(out); Defensive patterns
Strategy: validation
Validate before calling
if (!filename || !*filename)
throw std::invalid_argument("save_exr: filename is null or empty"); Type guard
bool valid_path(const char* p) { return p != nullptr && *p != '\0'; } Try / catch
try {
img.save_exr(path.c_str());
} catch (const CImgArgumentException& e) {
std::fprintf(stderr, "EXR save failed, no filename: %s\n", e.what());
} Prevention
- Guard getenv()/config path lookups for null
- Remember volumetric EXR saves only the first slice — warn on depth>1
- Centralize filename validation before all save_* calls
When it happens
Trigger: Calling CImg::save_exr(NULL) or forwarding a null filename through save(); typically from an uninitialized pointer, a getenv() that returned NULL, or a failed path computation whose result was not checked. Note this error requires OpenEXR support to even be reachable in some builds.
Common situations: EXR output path read from config/env that was unset; string helper returning NULL on failure; caller passing a std::string::c_str() of an empty-constructed-from-null pointer.
Related errors
- load_other(): Specified filename is (null).
- save_minc2(): Specified filename is (null).
- save_analyze(): Specified filename is (null).
- save_inr(): Specified filename is (null).
- load(): Specified filename is (null).
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/c98a88fd5bf6618c.
Report an issue: GitHub.