Yalantis/uCrop · error · CImgArgumentException

[cimg_appname_math_parser] CImg<

Error message

[cimg_appname_math_parser] CImg<%s>::%s: %s: Target scalar is constant, in expression '%s'.

What it means

The math parser's `fill()` function requires its first argument to be a mutable target (vector/array slot). If the compiled first argument is a constant scalar (literal or constant-folded expression), there is nothing to fill, so CImg throws this CImgArgumentException at expression-compile time.

Solutions

  1. Make the first argument a declared vector/variable (e.g. `v = vector(5); fill(v, value)`)
  2. Declare the target before filling: use `vector(N)` or similar to allocate it
  3. Fix typos in variable names that made the parser treat the argument as a literal
  4. Use the direct CImg::fill(value) C++ method instead of the expression form for plain constant fills

Example fix

// before
img.fill("fill(3, [1,2,3])"); // 3 is a constant scalar
// after
img.fill("v = vector(3); fill(v,[1,2,3])");
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the fill() target is a declared variable, not a literal:
// bad: "fill(3, ...)"; good: "v = vector(n); fill(v, ...)"
boolean fillTargetIsVariable(String expr) {
  java.util.regex.Matcher m = java.util.regex.Pattern.compile("fill\\(\\s*([^,)]+)").matcher(expr);
  return !m.find() || m.group(1).trim().matches("[A-Za-z_][A-Za-z0-9_]*");
}

Try / catch

try { img.fill(expr); } catch (CImgArgumentException e) { if (e.getMessage().contains("Target scalar is constant")) { throw new IllegalArgumentException("fill() target must be a declared vector/variable"); } throw e; }

Prevention

When it happens

Trigger: Calling `fill(<constant>, ...)` inside a math expression, e.g. `img.fill("fill(3, vector(5))")` where the first arg is the literal 3 rather than a named vector variable; also when the target expression is constant-folded into a scalar.

Common situations: Typos in variable names so the parser resolves a literal instead of a vector; misunderstanding that fill()'s first argument must be an lvalue-like vector reference; porting scripts where a variable was never declared with `vector(N)` or similar.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

              if (is_const_scalar(arg1)) _cimg_mp_const_scalar(cimg::factorial((int)mem[arg1]));
              _cimg_mp_scalar1(mp_factorial,arg1);
            }

            if (!std::strncmp(ss,"fibo(",5)) { // Fibonacci
              _cimg_mp_op("Function 'fibo()'");
              arg1 = compile(ss5,se1,depth1,0,block_flags);
              if (is_vector(arg1)) _cimg_mp_vector1_v(mp_fibonacci,arg1);
              if (is_const_scalar(arg1)) _cimg_mp_const_scalar(cimg::fibonacci((int)mem[arg1]));
              _cimg_mp_scalar1(mp_fibonacci,arg1);
            }

            if (!std::strncmp(ss,"fill(",5)) { // Fill
              _cimg_mp_op("Function 'fill()'");
              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);

View on GitHub (pinned to f788b534b4)