Yalantis/uCrop · error · CImgArgumentException

cimg::fopen(): File '%s', specified mode is (null).

Error message

cimg::fopen(): File '%s', specified mode is (null).

What it means

cimg::fopen() is CImg's thin wrapper over std fopen that validates its arguments before delegating to the OS. It throws CImgArgumentException when the caller passes a NULL mode string (e.g. fopen(path, NULL)); the path is still printed to help identify the call site. This is a pure caller-contract violation, not an I/O problem.

Source

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

    }

    // Open a file (similar to std:: fopen(), but with wide character support on Windows).
    inline std::FILE *std_fopen(const char *const path, const char *const mode);


    //! Open a file.
    /**
       \param path Path of the filename to open.
       \param mode C-string describing the opening mode.
       \return Opened file.
       \note Same as <tt>std::fopen()</tt> but throw a \c CImgIOException when
       the specified file cannot be opened, instead of returning \c 0.
    **/
    inline std::FILE *fopen(const char *const path, const char *const mode) {
      if (!path)
        throw CImgArgumentException("cimg::fopen(): Specified file path is (null).");
      if (!mode)
        throw CImgArgumentException("cimg::fopen(): File '%s', specified mode is (null).",
                                    path);
      std::FILE *res = 0;
      if (*path=='-' && (!path[1] || path[1]=='.')) {
        res = (*mode=='r')?cimg::_stdin():cimg::_stdout();
#if cimg_OS==2
        if (*mode && mode[1]=='b') { // Force stdin/stdout to be in binary mode
#ifdef __BORLANDC__
          if (setmode(_fileno(res),0x8000)==-1) res = 0;
#else
          if (_setmode(_fileno(res),0x8000)==-1) res = 0;
#endif
        }
#endif
      } else res = cimg::std_fopen(path,mode);
      if (!res) throw CImgIOException("cimg::fopen(): Failed to open file '%s' with mode '%s'.",
                                      path,mode);
      return res;
    }

View on GitHub (pinned to f788b534b4)

Solutions

  1. Pass a valid mode string literal such as "r", "rb", "w", or "wb" as the second argument to cimg::fopen()
  2. Check the caller that computes the mode string and give it a non-NULL default
  3. If the mode may be absent, guard with `if (mode)` before calling, or throw your own descriptive error

Example fix

// before
std::FILE *f = cimg::fopen(path, mode); // mode may be NULL
// after
if (!mode) mode = "rb";
std::FILE *f = cimg::fopen(path, mode);
Defensive patterns

Strategy: validation

Validate before calling

if (!mode || !*mode) mode = "rb"; // or throw app-level error before cimg::fopen

Type guard

bool validMode(const char *m){ return m && *m; }

Try / catch

try { f = cimg::fopen(path, mode); } catch (const cimg_library::CImgArgumentException &e) { log_error("bad fopen args: %s", e.what()); }

Prevention

When it happens

Trigger: Calling cimg::fopen(path, mode) with mode == NULL, typically when a mode string is built conditionally and ends up unset, or a function parameter is forwarded uninitialized.

Common situations: Passing a std::string::c_str() from an empty/unset variable used as mode; refactoring that removed a default "r"/"rb" argument; uninitialized const char* mode in JNI/Native code paths.

Related errors


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