Yalantis/uCrop · error · CImgArgumentException

[cimg_appname_math_parser] CImg<

Error message

[cimg_appname_math_parser] CImg<%s>::%s: %s: Argument '%s' is a vector of size %u (should be <=4), in expression '%s'.

What it means

Math parser argument error: a function in the evaluated expression received a vector-valued argument where a scalar (at most 4 components) is expected — e.g. a variable or list item of size >4 was passed to an operator or function that only accepts scalars or small vectors; the message names the offending argument and the full expression.

Solutions

  1. Pass at most 4 coordinate values (x,y,z,c)
  2. Verify the argument expression builds the intended coordinate vector, not a data array
  3. Split the call if more parameters are needed

Example fix

// before
J(x,y,z,c) = I(#0,x,y,z,c,extra);  // 5-element coord vector
// after
J(x,y,z,c) = I(#0,x,y,z,c);
Defensive patterns

Strategy: validation

Validate before calling

function checkCoordVectorSize(expr) {
  // coordinate vectors passed to coordinate functions must have <=4 elements
  const bad = [...expr.matchAll(/(I|J)\s*\(\s*#?\d+\s*,([^)]*)\)/g)]
    .filter(m => m[2].split(',').length > 4);
  return bad.length === 0;
}

Try / catch

try {
  img.evaluate(expr);
} catch (e) {
  if (/vector of size .*\(should be <=4\)/.test(String(e))) {
    // trim coordinate vector to x,y,z,c
  } else throw e;
}

Prevention

When it happens

Trigger: Calling coordinate-based functions (e.g. drawing/fill/interpolation ops in the math parser) passing a vector with 5+ elements as the coordinate argument.

Common situations: Passing an arbitrary data vector where coordinates were expected, forgetting that images have at most 4 dimensions (x,y,z,c).

Related errors


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

Appendix: source

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

          case 'c' :
            if (!std::strncmp(ss,"c2o(",4)) { // Coordinates to offset
              _cimg_mp_op("Function 'c2o()'");
              if (*ss4=='#') { // Index specified
                s0 = ss5; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
                p1 = compile(ss5,s0++,depth1,0,block_flags);
                p3 = 1;
                _cimg_mp_check_notnan_index(p1,ss5);
                _cimg_mp_check_list();
              } else { p1 = ~0U; s0 = ss4; p3 = 0; }
              s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
              pos = compile(s0,s1,depth1,0,block_flags);
              p2 = size(pos);
              if (p2) { // Coordinates specified as a vector
                if (p2>4) {
                  *s1 = 0; s1 = s0;
                  _cimg_mp_strerr;
                  throw CImgArgumentException("[" cimg_appname "_math_parser] "
                                              "CImg<%s>::%s: %s: Argument '%s' is a vector of size %u (should be <=4), "
                                              "in expression '%s'.",
                                              pixel_type(),_cimg_mp_calling_function,s_op,s1,p2,s0);
                }
                arg1 = pos + 1;
                arg2 = p2>1?pos + 2:0;
                arg3 = p2>2?pos + 3:0;
                arg4 = p2>3?pos + 4:0;
                arg5 = s1!=se1?compile(s1 + 1,se1,depth1,0,block_flags):0; // boundary conditions
                _cimg_mp_check_type(arg5,p3 + 2,1,0);
              } else { // Coordinates specified as scalars
                arg1 = pos; arg2 = arg3 = arg4 = arg5 = 0;
                if (s1<se1) {
                  s0 = ++s1; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
                  arg2 = compile(s1,s0,depth1,0,block_flags);
                  _cimg_mp_check_type(arg2,p3 + 2,1,0);
                  if (s0<se1) {
                    s1 = ++s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;

View on GitHub (pinned to f788b534b4)