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
- 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").
- Convert to lowercase and strip non-axis characters (commas, spaces) before calling.
- Add pre-call validation: check length <= 4, all chars in {x,y,z,c}, and no duplicates; raise an app-level error otherwise.
- 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
- Normalize case and strip separators (commas/spaces) from axes strings at input boundaries
- Reject duplicates early with a small validator mirroring CImg's rules
- Build axes strings programmatically from indices 0-3 mapped to "xyzc" rather than hand-typing
- Add a unit test covering each invalid form: uppercase, >4 chars, duplicated axis
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
- "[" cimg_appname "_math_parser] CImg<%s>: Function 'polygon(
- "[" cimg_appname "_math_parser] CImg<%s>: Function 'polygon(
- invert(): Specified lambda (%g) should be >=0.
- sort(): Invalid specified axis '%c' (should be { x | y | z |
- %s
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/01902397b6138638.
Report an issue: GitHub.