Yalantis/uCrop · error · CImgArgumentException

save_pandore(): Specified filename is (null).

Error message

save_pandore(): Specified filename is (null).

What it means

CImg's save_pandore() writes the image in the PANDORE file format to either a FILE* or a filename. Because it needs one of the two output targets, it throws CImgArgumentException when both are null. This is a pure caller-contract check performed before any I/O happens.

Source

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

          else if (sizeof(unsigned int)==4) { __cimg_save_pandore_case(unsigned int); } \
          else if (sizeof(unsigned short)==4) { __cimg_save_pandore_case(unsigned short); } \
          else throw CImgIOException(_cimg_instance \
                                     "save_pandore(): Unsupported datatype for file '%s'.",\
                                     cimg_instance, \
                                     filename?filename:"(FILE*)"); \
        } else if (id==4 || id==7 || id==10 || id==18 || id==21 || id==25 || id==29 || id==33) { \
          if (sizeof(double)==4) { __cimg_save_pandore_case(double); } \
          else if (sizeof(float)==4) { __cimg_save_pandore_case(float); } \
          else throw CImgIOException(_cimg_instance \
                                     "save_pandore(): Unsupported datatype for file '%s'.",\
                                     cimg_instance, \
                                     filename?filename:"(FILE*)"); \
        } \
        saved = true; \
      }

      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_pandore(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty()) { cimg::fempty(file,filename); return *this; }

      std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
      unsigned char header[36] = { 'P','A','N','D','O','R','E','0','4',0,0,0,
                                   0,0,0,0,'C','I','m','g',0,0,0,0,0,
                                   'N','o',' ','d','a','t','e',0,0,0,0 };
      unsigned int nbdims, dims[5] = {};
      bool saved = false;
      _cimg_save_pandore_case(1,1,1,"uint8",2);
      _cimg_save_pandore_case(1,1,1,"int8",3);
      _cimg_save_pandore_case(1,1,1,"uint16",3);
      _cimg_save_pandore_case(1,1,1,"int16",3);
      _cimg_save_pandore_case(1,1,1,"uint32",3);
      _cimg_save_pandore_case(1,1,1,"int32",3);
      _cimg_save_pandore_case(1,1,1,"uint64",3);
      _cimg_save_pandore_case(1,1,1,"int64",3);

View on GitHub (pinned to f788b534b4)

Solutions

  1. Pass a valid non-null filename, e.g. img.save_pandore("out.pan").
  2. If writing to an already-open stream, pass the std::FILE* instead of a filename.
  3. Guard the path upstream: if (path && *path) img.save_pandore(path); else handle the missing path.

Example fix

// before
img.save_pandore(); // filename defaults to 0
// after
img.save_pandore("output.pan");
Defensive patterns

Strategy: validation

Validate before calling

if (!filename || !*filename) { /* choose default or abort */ filename = "output.pan"; }
img.save_pandore(filename);

Type guard

bool hasOutputTarget(std::FILE *f, const char *name) { return f != nullptr || (name != nullptr && name[0] != '\0'); }

Try / catch

try { img.save_pandore(path.c_str()); }
catch (cimg_library::CImgArgumentException &e) { std::fprintf(stderr, "bad save args: %s\n", e.what()); }

Prevention

When it happens

Trigger: Calling save_pandore() with no arguments (default filename is 0/null) or explicitly passing NULL as the filename while also not passing a FILE*.

Common situations: Passing a std::string's c_str() from a variable that was never set, propagating an empty/null path from upper layers, or accidentally calling the no-argument overload expecting a default file name.

Related errors


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