Yalantis/uCrop · error · CImgArgumentException
remove(): Invalid remove request at positions %u->%u.
Error message
remove(): Invalid remove request at positions %u->%u.
What it means
CImgList::remove(pos1,pos2) throws when the normalized start position npos1 is greater than or equal to the list size _width, meaning the entire requested removal range lies past the end of the list. Nothing can be removed, so the library raises CImgArgumentException with the normalized position range.
Solutions
- Check list.size() and skip the call when pos1 >= size() before removing
- Clamp positions: pos1 = min(pos1, size-1), pos2 = min(pos2, size-1)
- Verify the range wasn't already removed (guard against double removal)
Example fix
// before list.remove(4, 6); // throws when list.size() <= 4 // after if (list.size() > 4) list.remove(4, std::min(6u, list.size() - 1));
Defensive patterns
Strategy: validation
Validate before calling
if (list.is_empty() || std::min(pos1,pos2) >= list.size()) return; // skip out-of-range removal
Try / catch
try { list.remove(pos1, pos2); } catch (const CImgArgumentException& e) { /* log and skip */ } Prevention
- Check size() before batch removal
- Avoid double removal of the same range
- Use size()-1 as the maximum valid index
When it happens
Trigger: list.remove(pos1,pos2) where min(pos1,pos2) >= list.size(), e.g. removing indices 4->6 from a 4-element list, or calling remove on an empty list.
Common situations: Reusing cached index ranges after the list shrank; removing a batch twice (second call is out of range); calling on an empty list built from a failed load.
Related errors
- images(): Specified sub-list indices (%u->%u) are out of…
- load_cimg(): Invalid specified coordinates…
- "[" cimg_appname "_math_parser] CImg<
- "[" cimg_appname "_math_parser] CImg<
- "[" cimg_appname "_math_parser] CImg<
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/b27f4cd1bca85d12.
Report an issue: GitHub.
Appendix: source
Thrown at ucrop/src/main/jni/CImg.h:65952
//! Insert n copies of the list \c list at position \c pos of the current list \newinstance.
template<typename t>
CImgList<T> get_insert(const unsigned int n, const CImgList<t>& list, const unsigned int pos=~0U,
const bool is_shared=false) const {
return (+*this).insert(n,list,pos,is_shared);
}
//! Remove all images between from indexes.
/**
\param pos1 Starting index of the removal.
\param pos2 Ending index of the removal.
**/
CImgList<T>& remove(const unsigned int pos1, const unsigned int pos2) {
const unsigned int
npos1 = pos1<pos2?pos1:pos2,
tpos2 = pos1<pos2?pos2:pos1,
npos2 = tpos2<_width?tpos2:_width - 1;
if (npos1>=_width)
throw CImgArgumentException(_cimglist_instance
"remove(): Invalid remove request at positions %u->%u.",
cimglist_instance,
npos1,tpos2);
else {
if (tpos2>=_width)
throw CImgArgumentException(_cimglist_instance
"remove(): Invalid remove request at positions %u->%u.",
cimglist_instance,
npos1,tpos2);
for (unsigned int k = npos1; k<=npos2; ++k) _data[k].assign();
const unsigned int nb = 1 + npos2 - npos1;
if (!(_width-=nb)) return assign();
if (_width>(_allocated_width>>4) || _allocated_width<=16) { // Removing items without reallocation
if (npos1!=_width)
std::memmove((void*)(_data + npos1),(void*)(_data + npos2 + 1),sizeof(CImg<T>)*(_width - npos1));
std::memset((void*)(_data + _width),0,sizeof(CImg<T>)*nb);
} else { // Removing items with reallocationView on GitHub (pinned to f788b534b4)