Yalantis/uCrop · error · CImgArgumentException

[" cimg_appname "_math_parser] CImg<%s>::%s: Undefined varia

Error message

[" cimg_appname "_math_parser] CImg<%s>::%s: Undefined variable '%s' in expression '%s'.

What it means

The CImg math parser tokenizes the expression and resolves each identifier. When an item is neither a known variable, named constant, function, nor operator, the parser reaches the 'unknown item' fallback. If the token is followed by something indicating a value context (is_sth), it reports 'Undefined variable' naming the token after ellipsizing it to 64 chars.

Source

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

#ifdef cimg_mp_operator_dollar
        if (*ss=='$' && ss1<se) // External variable '$varname'
          _cimg_mp_const_scalar(cimg_mp_operator_dollar(variable_name._data + 1));
#endif

        // No known item found, assuming this is an already initialized variable.
        if (cimg::is_varname(variable_name)) { // Valid variable name
          get_variable_pos(variable_name,arg1,arg2);
          arg1 = arg2!=~0U?reserved_label[arg2]:arg1!=~0U?variable_pos[arg1]:~0U;
          if (arg1!=~0U) _cimg_mp_return(arg1);
        }

        // Reached an unknown item -> error.
        c1 = *se1;
        cimg::strellipsize(variable_name,64);
        _cimg_mp_strerr;
        if (is_sth)
          throw CImgArgumentException("[" cimg_appname "_math_parser] "
                                      "CImg<%s>::%s: Undefined variable '%s' in expression '%s'.",
                                      pixel_type(),_cimg_mp_calling_function,
                                      variable_name._data,s0);
        s1 = std::strchr(ss,'(');
        s_op = s1 && c1==')'?"function call":"item";
        throw CImgArgumentException("[" cimg_appname "_math_parser] "
                                    "CImg<%s>::%s: Unrecognized %s '%s' in expression '%s'.",
                                    pixel_type(),_cimg_mp_calling_function,
                                    s_op,variable_name._data,s0);
      }

      // Evaluation procedure.
      double operator()(const double x, const double y, const double z, const double c) {
        mem[_cimg_mp_slot_x] = x; mem[_cimg_mp_slot_y] = y; mem[_cimg_mp_slot_z] = z; mem[_cimg_mp_slot_c] = c;
        for (p_code = code; p_code<p_code_end; ++p_code) {
          opcode._data = p_code->_data;
          const ulongT target = opcode[1];
          mem[target] = _cimg_mp_defunc(*this);

View on GitHub (pinned to f788b534b4)

Solutions

  1. Check the identifier spelling against the variables you actually defined/passed.
  2. Define the variable before evaluation (assign it in the expression or pass it as a named value).
  3. Use only built-in symbols valid for your CImg version (check docs for the version in use).
  4. Simplify the expression to isolate which token is unresolved.
  5. Add a sanity test that evaluates the expression with known inputs before deploying.

Example fix

// before
img.fill(myValue*2); // 'myValue' never defined
// after
img.fill(42*2);       // or define/bind myValue before evaluation
Defensive patterns

Strategy: validation

Validate before calling

Set<String> defined = Set.of("i","x","y","z","c","pi"); // plus user-bound names
for (String id : extractIdentifiers(expression))
    if (!defined.contains(id)) throw new IllegalArgumentException("undefined variable: " + id);

Try / catch

try {
    img.fill(expression);
} catch (CImgInstantiationException e) {
    if (e.getMessage().contains("Undefined variable")) {
        // log offending identifier from message, bind or correct it
    }
    throw e;
}

Prevention

When it happens

Trigger: Evaluating an expression referencing an identifier never assigned (e.g. via named variables passed to fill()/math()), a misspelled built-in constant, or using a variable outside the scope where it was defined.

Common situations: Typo in variable names inside fill() formulas; forgetting to pass named values/images to the expression; expressions copied from examples that rely on different predefined variables; renaming variables without updating expressions.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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