Yalantis/uCrop · error · CImgArgumentException

permute_axes(): Invalid specified axes order '%s'.

Error message

permute_axes(): Invalid specified axes order '%s'.

What it means

CImg's permute_axes() accepts an axes_order string of up to 4 characters that must be some permutation of 'x','y','z','c'. The parsing loop marks is_error if the string is longer than 4 characters, contains any character outside {x,y,z,c}, or repeats an axis (any n_axes count > 1). On error it throws CImgArgumentException showing the supplied order string.

Source

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

    }

    //! Permute axes order \newinstance.
    CImg<T> get_permute_axes(const char *const axes_order) const {
      const T foo = (T)0;
      return _permute_axes(axes_order,foo);
    }

    unsigned int _permute_axes_uicase(const char *const axes_order) const { // Convert axes to integer case number
      unsigned char s_axes[4] = { 0,1,2,3 }, n_axes[4] = { };
      bool is_error = false;
      if (axes_order) for (unsigned int l = 0; axes_order[l]; ++l) {
          int c = cimg::lowercase(axes_order[l]);
          if (l>=4 || (c!='x' && c!='y' && c!='z' && c!='c')) { is_error = true; break; }
          else { ++n_axes[c%=4]; s_axes[l] = (unsigned char)c; }
        }
      is_error|=(*n_axes>1) || (n_axes[1]>1) || (n_axes[2]>1) || (n_axes[3]>1);
      if (is_error)
        throw CImgArgumentException(_cimg_instance
                                    "permute_axes(): Invalid specified axes order '%s'.",
                                    cimg_instance,
                                    axes_order);
      return (s_axes[0]<<12) | (s_axes[1]<<8) | (s_axes[2]<<4) | (s_axes[3]);
    }

    bool _permute_axes_is_optim(const unsigned int uicase) const { // Determine cases where nothing has to be done
      const unsigned int co = ((_width>1)<<3)|((_height>1)<<2)|((_depth>1)<<1)|(_spectrum>1);
      if (co<=2 || uicase==0x0123) return true;
      switch (uicase) {
      case (0x0132) : if ((co>=4 && co<=6) || (co>=8 && co<=10) || (co>=12 && co<=14)) return true; break;
      case (0x0213) : if ((co>=3 && co<=5) || (co>=8 && co<=13)) return true; break;
      case (0x0231) : if (co==3 || co==4 || (co>=8 && co<=12)) return true; break;
      case (0x0312) : if (co==4 || co==6 || co==8 || co==9 || co==10 || co==12 || co==14) return true; break;
      case (0x0321) : if (co==4 || (co>=8 && co<=10) || co==12) return true; break;
      case (0x1023) : if (co>=3 && co<=11) return true; break;
      case (0x1032) : if ((co>=4 && co<=6) || (co>=8 && co<=10)) return true; break;
      case (0x1203) : if (co>=3 && co<=9) return true; break;

View on GitHub (pinned to f788b534b4)

Solutions

  1. Supply a string whose characters are exactly a permutation of x, y, z, c, with each axis appearing at most once (e.g. "zyxc", "yx").
  2. Convert to lowercase and strip non-axis characters (commas, spaces) before calling.
  3. Add pre-call validation: check length <= 4, all chars in {x,y,z,c}, and no duplicates; raise an app-level error otherwise.
  4. If you need to permute by indices, generate the string programmatically from indices 0-3 mapped to "xyzc".

Example fix

// before
img.permute_axes("XYZC"); // uppercase and 4+ chars rejected per rules
// after
img.permute_axes("zyxc"); // lowercase permutation of x,y,z,c
Defensive patterns

Strategy: validation

Validate before calling

// C++
bool isValidAxesOrder(const std::string& order) {
    if (order.empty() || order.size() > 4) return false;
    int count[4] = {0,0,0,0};
    for (char ch : order) {
        int i = std::string("xyzc").find(std::tolower(ch));
        if (i < 0 || ++count[i] > 1) return false;
    }
    return true;
}
std::string order = normalize(userOrder); // lowercase, strip separators
if (!isValidAxesOrder(order)) throw std::invalid_argument("axes_order must be a permutation of xyzc");
img.permute_axes(order.c_str());

Type guard

bool isValidAxesOrder(const std::string& s) {
    if (s.empty() || s.size() > 4) return false;
    int n[4] = {0,0,0,0};
    for (char c : s) { int i = std::string("xyzc").find(c); if (i<0 || ++n[i]>1) return false; }
    return true;
}

Try / catch

try {
    img.permute_axes(order.c_str());
} catch (const cimg_library::CImgArgumentException& e) {
    // log e.what(); keep original axis order
}

Prevention

When it happens

Trigger: Calling CImg<T>::permute_axes(axes_order) with: a string longer than 4 chars (e.g. "xyzcxyz"), invalid characters (uppercase "XYZC", digits, whitespace), or a duplicated axis like "xxy" or "xyzx". Also an empty or short string like "xy" — short strings are allowed only as abbreviations, but "xyy" is not.

Common situations: Building the axes string dynamically from user config with wrong case ('YX'); typo'd axis strings ('xyyz'); porting code from libraries that use 0-3 numeric permutations; locale/formatting bugs appending separators like commas ('x,y,z,c').

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/01902397b6138638. Report an issue: GitHub.