Yalantis/uCrop · error · CImgIOException
cimg::dialog(): No display available.
Error message
cimg::dialog(): No display available.
What it means
cimg::dialog() renders a graphical message box with up to six buttons using the CImg display layer. When CImg was compiled without display support (cimg_display==0, i.e. no X11/Windows/GDI/SDL backend available at compile time) the function is a stub that immediately throws CImgIOException because there is no display to draw on.
Solutions
- Replace cimg::dialog() with non-interactive reporting (log the message, fprintf/std::cerr, or your UI framework's dialog) when targeting headless platforms.
- Check the environment before calling: if cimg_display==0 (or DISPLAY is unset on Linux), take an alternate code path instead of invoking the dialog.
- If a display is expected, rebuild CImg with a display backend enabled (install X11 headers and compile with cimg_display=1, default) or run under X (e.g. xvfb) on headless machines.
- In library code, never call cimg::dialog(); keep interactive UI out of library/JNI layers and surface errors to the caller instead.
Example fix
// before
cimg::dialog("Error", "Failed to load image", "OK"); // throws on headless/Android builds
// after
#if cimg_display!=0
cimg::dialog("Error", "Failed to load image", "OK");
#else
fprintf(stderr, "Failed to load image\n");
#endif Defensive patterns
Strategy: try-catch
Validate before calling
// Detect headless/no-display builds before calling dialog
bool hasDisplay() {
#if cimg_display==0
return false;
#else
const char* d = std::getenv("DISPLAY");
return d != nullptr && *d != '\0';
#endif
}
if (!hasDisplay()) { fprintf(stderr, "%s\n", msg); } else { cimg::dialog(title, msg, "OK"); } Try / catch
try {
cimg::dialog("Error", msg, "OK");
} catch (CImgIOException& e) {
// No display available: degrade to console logging
std::cerr << "Dialog unavailable: " << msg << "\n";
} Prevention
- Never use cimg::dialog() in library, JNI, server, or CI code; keep it in desktop GUI layers only.
- Compile-time check cimg_display and provide a logging fallback branch for cimg_display==0 builds.
- On headless Linux boxes, install xvfb and run with xvfb-run if interactive dialogs are truly needed.
- Log the message via fprintf/std::cerr as the default path and treat dialogs as an optional enhancement.
When it happens
Trigger: Calling cimg::dialog() (directly, or indirectly via functions that fall back to it, e.g. when an image cannot be loaded and CImg offers an interactive dialog) in a build where cimg_display is 0 — headless Linux servers, cross-compiled Android NDK builds (as in ucrop's JNI build), or projects compiled with -Dcimg_display=0.
Common situations: Running a GUI-using CImg program on a headless server/CI container built without X11 headers; Android NDK builds where no display backend exists; Docker images without X/libx11-dev installed; intentionally disabling display support for a library build but still calling interactive helpers.
Understand the failure class
Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.
Related errors
- cimg::dialog(): No buttons have been defined.
- CImgDisplay(): No display available.
- save_pandore(): Unsupported datatype for file
- assign(): Invalid assignment request of shared instance from
- assign(): Shared image instance has overlapping memory.
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/f3d879d5b5a95ba4.
Report an issue: GitHub.
Appendix: source
Thrown at ucrop/src/main/jni/CImg.h:70273
\param logo Image logo displayed at the left of the main message.
\param is_centered Tells if the dialog window must be centered on the screen.
\return Index of clicked button (from \c 0 to \c 5), or \c -1 if the dialog window has been closed by the user.
\note
- Up to 6 buttons can be defined in the dialog window.
- The function returns when a user clicked one of the button or closed the dialog window.
- If a button text is set to 0, the corresponding button (and the following) will not appear in the dialog box.
At least one button must be specified.
**/
template<typename t>
inline int dialog(const char *const title, const char *const msg,
const char *const button1_label, const char *const button2_label,
const char *const button3_label, const char *const button4_label,
const char *const button5_label, const char *const button6_label,
const CImg<t>& logo, const bool is_centered=false) {
#if cimg_display==0
cimg::unused(title,msg,button1_label,button2_label,button3_label,button4_label,button5_label,button6_label,
logo._data,is_centered);
throw CImgIOException("cimg::dialog(): No display available.");
#else
static const unsigned char
black[] = { 0,0,0 }, white[] = { 255,255,255 }, gray[] = { 200,200,200 }, gray2[] = { 150,150,150 };
// Create buttons and canvas graphics.
CImgList<unsigned char> buttons, cbuttons, sbuttons;
if (button1_label) {
CImg<unsigned char>().draw_text(0,0,button1_label,black,gray,1,13).move_to(buttons);
if (button2_label) {
CImg<unsigned char>().draw_text(0,0,button2_label,black,gray,1,13).move_to(buttons);
if (button3_label) {
CImg<unsigned char>().draw_text(0,0,button3_label,black,gray,1,13).move_to(buttons);
if (button4_label) {
CImg<unsigned char>().draw_text(0,0,button4_label,black,gray,1,13).move_to(buttons);
if (button5_label) {
CImg<unsigned char>().draw_text(0,0,button5_label,black,gray,1,13).move_to(buttons);
if (button6_label) {
CImg<unsigned char>().draw_text(0,0,button6_label,black,gray,1,13).move_to(buttons);View on GitHub (pinned to f788b534b4)