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

  1. Replace cimg::dialog() with non-interactive reporting (log the message, fprintf/std::cerr, or your UI framework's dialog) when targeting headless platforms.
  2. 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.
  3. 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.
  4. 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

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


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)