Yalantis/uCrop · error · CImgIOException
save_gif_external(): Failed to save file
Error message
save_gif_external(): Failed to save file '%s' with external command 'magick/convert'.
What it means
save_gif_external() assembles an ImageMagick 'magick'/'convert' command line from per-frame temp files and runs it via cimg::system(). A nonzero exit status from that external process throws this CImgIOException — the GIF was not written because ImageMagick itself failed.
Solutions
- Install ImageMagick or set the correct binary via CImg_IMAGEMAGICK_PATH env / cimg::imagemagick_path().
- Reduce the number of frames or write to a shorter temp directory to shrink the command line.
- Verify the exact ImageMagick invocation manually with the same arguments to see the real error.
Example fix
// before
list.save_gif_external("anim.gif"); // fails if ImageMagick absent
// after
if (std::system("command -v convert >/dev/null")!=0)
throw std::runtime_error("ImageMagick not installed");
list.save_gif_external("anim.gif"); Defensive patterns
Strategy: fallback
Validate before calling
if (std::system("command -v magick >/dev/null 2>&1 && command -v convert >/dev/null 2>&1") != 0) {
fprintf(stderr, "ImageMagick unavailable\n");
return false;
} Try / catch
try { list.save_gif_external(out); }
catch (CImgIOException &e) { /* save frames individually or use a native GIF encoder */ } Prevention
- Install ImageMagick in deployment images.
- Keep frame counts/temp paths short to avoid command-line limits.
- Set imagemagick_path()/env correctly for IM6 vs IM7.
When it happens
Trigger: cimg::system() returns !=0 when executing the imagemagick command: 'magick'/'convert' binary not installed, bad imagemagick_path(), command-line length limits exceeded, or invalid frame files.
Common situations: CI containers without ImageMagick; IM6 'convert' vs IM7 'magick' naming differences; very long frame lists exceeding shell/command length limits (common on Android execve limits).
Related errors
- load_gif_external(): Failed to open file
- load_gif_external(): Specified filename is (null) or does…
- cimg::system() : Command
- load_gzip_external(): Failed to open file
- load_imagemagick_external(): Failed to load file
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/7c7c5b088829f500.
Report an issue: GitHub.
Appendix: source
Thrown at ucrop/src/main/jni/CImg.h:68054
else if (frame._spectrum==1) frame.assign(frame.get_resize(-100,-100,1,3),false);
else if (frame._spectrum==2)
frame.assign(frame.get_resize(-100,-100,1,4).draw_image(0,0,0,2,frame.get_shared_channel(0)),false);
frame.save(filename_tmp2);
}
cimg_snprintf(command,command._width,"\"%s\" -delay %u -loop %u -dispose previous",
cimg::imagemagick_path(),
(unsigned int)std::max(0.f,cimg::round(100/fps)),
nb_loops);
CImg<ucharT>::string(command).move_to(filenames,0);
cimg_snprintf(command,command._width,"\"%s\"",
CImg<charT>::string(filename)._system_strescape().data());
CImg<ucharT>::string(command).move_to(filenames);
CImg<charT> _command = filenames>'x';
cimg_for(_command,p,char) if (!*p) *p = ' ';
_command.back() = 0;
if (cimg::system(_command,cimg::imagemagick_path())!=0)
throw CImgIOException(_cimglist_instance
"save_gif_external(): Failed to save file '%s' with external command 'magick/convert'.",
cimglist_instance,
filename);
if (!cimg::path_exists(filename))
throw CImgIOException(_cimglist_instance
"save_gif_external(): Failed to save file '%s' with external command 'magick/convert'.",
cimglist_instance,
filename);
cimglist_for_in(*this,1,filenames._width - 1,l) std::remove(filenames[l]);
return *this;
}
//! Save list as a YUV image sequence file.
/**
\param filename Filename to write data to.
\param chroma_subsampling Type of chroma subsampling. Can be <tt>{ 420 | 422 | 444 }</tt>.
\param is_rgb Tells if the RGB to YUV conversion must be done for saving.
**/View on GitHub (pinned to f788b534b4)