Yalantis/uCrop · error · CImgArgumentException

[cimg_appname_math_parser] CImg<%s>::%s: %s: Invalid loop va

Error message

[cimg_appname_math_parser] CImg<%s>::%s: %s: Invalid loop variable name '%s', in expression '%s'.

What it means

Loop constructs in the math parser (`for`, `while`, `repeat`, `do`) with the 3-argument form take a loop variable name as the first argument. CImg validates the name with cimg::is_varname; if the extracted token is not a legal variable name (empty, starts with a digit, contains operators/illegal characters) it throws this error, truncating the name to 64 chars in the message.

Source

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

              s0 = ss5; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
              arg1 = compile(ss5,s0,depth1,0,block_flags); // Object to fill
              if (is_const_scalar(arg1)) {
                _cimg_mp_strerr;
                throw CImgArgumentException("[" cimg_appname "_math_parser] "
                                            "CImg<%s>::%s: %s: Target scalar is constant, "
                                            "in expression '%s'.",
                                            pixel_type(),_cimg_mp_calling_function,s_op,ss);
              }
              s1 = ++s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
              p1 = code._width;

              if (s1<se1) { // Version with 3 arguments
                variable_name.assign(s0,(unsigned int)(s1 + 1 - s0)).back() = 0;
                cimg::strpare(variable_name,false,true);
                if (!cimg::is_varname(variable_name)) { // Invalid variable name
                  cimg::strellipsize(variable_name,64);
                  _cimg_mp_strerr;
                  throw CImgArgumentException("[" cimg_appname "_math_parser] "
                                              "CImg<%s>::%s: %s: Invalid loop variable name '%s', "
                                              "in expression '%s'.",
                                              pixel_type(),_cimg_mp_calling_function,s_op,
                                              variable_name._data,s0);
                }
                get_variable_pos(variable_name,arg2,arg3);
                arg2 = arg3!=~0U?reserved_label[arg3]:arg2!=~0U?variable_pos[arg2]:~0U; // Variable slot
                if (arg2!=~0U && (!is_scalar(arg2) ||
                                  is_const_scalar(arg2))) { // Variable is not a vector or is a constant->error
                  cimg::strellipsize(variable_name,64);
                  _cimg_mp_strerr;
                  throw CImgArgumentException("[" cimg_appname "_math_parser] "
                                              "CImg<%s>::%s: %s: Invalid type '%s' for variable '%s' "
                                              "(expected 'scalar'), in expression '%s'.",
                                              pixel_type(),_cimg_mp_calling_function,s_op,
                                              s_type(arg2)._data,variable_name._data,s0);
                } else if (arg2==~0U) { // Variable does not exist -> create it
                  arg2 = scalar();

View on GitHub (pinned to f788b534b4)

Solutions

  1. Pass a valid variable name as first argument: `for(i=0, i<5, i++, ...)` or `repeat(5, i, ...)`
  2. Ensure the name matches cimg::is_varname: letters/digits/underscore, not starting with a digit, no operators
  3. Reorder arguments if you inverted the range and variable positions
  4. Use the 2-argument loop form (automatic variable) if you don't need a named loop variable

Example fix

// before
img.fill("repeat(10,x+1)"); // '10' is not a variable name in 3-arg form
// after
img.fill("repeat(10,i,x+1)");
Defensive patterns

Strategy: type-guard

Validate before calling

static final java.util.regex.Pattern VAR = java.util.regex.Pattern.compile("[A-Za-z_][A-Za-z0-9_]*");
boolean isValidLoopVar(String name) { return name != null && VAR.matcher(name).matches(); }

Type guard

boolean isVarName(String s) { return s != null && s.matches("[A-Za-z_][A-Za-z0-9_]*"); }

Try / catch

try { img.fill(expr); } catch (CImgArgumentException e) { if (e.getMessage().contains("Invalid loop variable name")) { throw new IllegalArgumentException("Loop's first argument must be a valid identifier"); } throw e; }

Prevention

When it happens

Trigger: `repeat(1x,index,...)` style 3-argument loops where the first token is not a valid identifier, e.g. `repeat(10,2,x+y)` (expression instead of variable name), `for(0,5,i,...)` with a literal as first arg, or names like `2i`, `my-var`, or an empty string.

Common situations: Misremembering argument order of for/repeat (thinking first arg is the range); G'MIC-to-CImg expression porting where loop syntax differs; typos such as a missing variable and passing the iteration count first.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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