Yalantis/uCrop · error · CImgArgumentException

[" cimg_appname "_math_parser] CImg<

Error message

[" cimg_appname "_math_parser] CImg<%s>::%s: %s: Literal %s contains more than one byte, in expression '%s'.

What it means

CImg's math parser supports character literals (e.g. 'A') as single-byte values. This error is thrown when a quoted literal intended as a character contains more than one byte — the parser cannot represent it as a single scalar. Note the parser works on bytes, so multi-byte UTF-8 characters also trigger it.

Solutions

  1. Reduce the quoted literal to exactly one ASCII character.
  2. For multi-byte characters, use the byte value(s) explicitly, e.g. via char codes or multiple one-byte literals.
  3. Strip or replace typographic/unicode quotes with straight ASCII quotes.
  4. Sanitize expressions built from user/config input to ASCII before passing to CImg.
  5. If a string is needed, use CImg string-handling functions instead of char literals.

Example fix

// before
img.fill("X=='é'"); // multi-byte UTF-8 literal
// after
img.fill("X==233"); // explicit code point, or single-byte 'e'
Defensive patterns

Strategy: validation

Validate before calling

String s = "'X'";
if (s.length() - 2 != 1 || !isAscii(s.charAt(1))) throw new IllegalArgumentException("char literal must be one ASCII byte");

Try / catch

try {
    img.fill(expression);
} catch (CImgInstantiationException e) {
    if (e.getMessage().contains("contains more than one byte")) {
        // replace offending literal with a numeric code point
    }
    throw e;
}

Prevention

When it happens

Trigger: Evaluating an expression containing a multi-character quoted literal such as 'ab' or a multi-byte UTF-8 character like 'é' where a single-char literal is expected (parsed via the string-literal branch that ends with _cimg_mp_const_scalar((unsigned char)*variable_name)).

Common situations: Using typographic quotes or accented characters inside fill() expressions; accidentally leaving two characters inside quotes; non-ASCII input from config files or user text pasted into expressions.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

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

        // Char / string initializer.
        if (*se1=='\'' &&
            ((se1>ss && *ss=='\'') ||
            (se1>ss1 && *ss=='_' && *ss1=='\''))) {
          if (*ss=='_') { _cimg_mp_op("Char initializer"); s1 = ss2; }
          else { _cimg_mp_op("String initializer"); s1 = ss1; }
          arg1 = (unsigned int)(se1 - s1); // Original string length
          if (arg1) {
            CImg<charT>(s1,arg1 + 1).move_to(variable_name).back() = 0;
            cimg::strunescape(variable_name);
            arg1 = (unsigned int)std::strlen(variable_name);
          }
          if (!arg1) _cimg_mp_return(0); // Empty string -> 0
          if (*ss=='_') {
            if (arg1==1) _cimg_mp_const_scalar((unsigned char)*variable_name);
            cimg::strellipsize(variable_name,64);
            _cimg_mp_strerr;
            throw CImgArgumentException("[" cimg_appname "_math_parser] "
                                        "CImg<%s>::%s: %s: Literal %s contains more than one byte, "
                                        "in expression '%s'.",
                                        pixel_type(),_cimg_mp_calling_function,s_op,
                                        ss1,s0);
          }
          pos = vector(arg1);
          CImg<ulongT>::vector((ulongT)mp_string_init,pos,arg1).move_to(l_opcode);
          CImg<ulongT>(1,arg1/sizeof(ulongT) + (arg1%sizeof(ulongT)?1:0)).move_to(l_opcode);
          std::memcpy((char*)l_opcode[1]._data,variable_name,arg1);
          (l_opcode>'y').move_to(is_inside_begin || is_new_variable_assignment?code:code_begin);
          return_comp = is_new_variable_assignment;
          if (!return_comp) set_reserved_vector(pos); // Prevent from being used in further optimization
          _cimg_mp_return(pos);
        }

        // Vector initializer [ ... ].
        if (*ss=='[' && *se1==']') {
          _cimg_mp_op("Vector initializer");

View on GitHub (pinned to f788b534b4)