Yalantis/uCrop · error · CImgArgumentException
cimg::dialog(): No buttons have been defined.
Error message
cimg::dialog(): No buttons have been defined.
What it means
cimg::dialog() builds its message box by rendering each non-null button label into button images; the box needs at least one button to draw. If every button*_label argument is NULL, the buttons list stays empty (buttons._width == 0) and CImg throws CImgArgumentException because a dialog with no clickable buttons cannot be constructed.
Solutions
- Always pass at least one non-null button label, e.g. cimg::dialog("Title","Msg","OK") instead of passing NULL for button1_label.
- Validate the label arguments (or the array feeding them) before calling dialog(), and fall back to a default "OK" label when none are provided.
- Check the argument order — the first non-null label lands in button1; make sure the intended label is not shifted into a wrong or unused slot.
- If button labels are dynamic, guard the call: only invoke cimg::dialog() when the labels vector is non-empty, otherwise use a plain log message.
Example fix
// before
cimg::dialog("Load error", "Cannot open file", NULL, NULL, NULL, NULL, NULL, NULL); // no buttons -> throws
// after
if (buttonLabels.empty()) buttonLabels.push_back("OK");
cimg::dialog("Load error", "Cannot open file", buttonLabels[0],
buttonLabels.size()>1?buttonLabels[1].c_str():NULL,
buttonLabels.size()>2?buttonLabels[2].c_str():NULL,
NULL, NULL, NULL); Defensive patterns
Strategy: validation
Validate before calling
// Require at least one non-null button label before opening a dialog
bool hasButton(const char* b1, const char* b2, const char* b3,
const char* b4, const char* b5, const char* b6) {
return b1 || b2 || b3 || b4 || b5 || b6;
}
if (hasButton(b1,b2,b3,b4,b5,b6)) {
cimg::dialog(title, msg, b1?b1:"", b2, b3, b4, b5, b6);
} else {
cimg::dialog(title, msg, "OK", NULL, NULL, NULL, NULL, NULL); // default button
} Try / catch
try {
cimg::dialog(title, msg, b1, b2, b3, b4, b5, b6);
} catch (CImgArgumentException& e) {
std::cerr << "Dialog error: " << e.what() << "\n";
cimg::dialog(title, msg, "OK", NULL, NULL, NULL, NULL, NULL); // retry with default
} Prevention
- Always supply at least one button label (typically "OK") in every cimg::dialog() call.
- If labels are built dynamically, assert the list is non-empty before invoking the dialog.
- Double-check argument order/positions so the intended label lands in button1_label rather than an unused slot.
- Prefer a small wrapper function with a default button so callers can never pass all-null labels.
When it happens
Trigger: Calling cimg::dialog(title,msg,...) with all six button label arguments set to NULL (or passing only NULLs on a path where default labels were expected), causing the `if (!buttons._width)` check to fail.
Common situations: Programmatically building button labels and passing NULL when the label list ends up empty; forwarding user-supplied/optional button names that were never initialized; porting code from another dialog API where a null-button dialog is legal; typos where the single intended "OK" label is passed in the wrong position or left NULL.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- cimg::dialog(): No display available.
- load_ascii(): Invalid ascii header in file
- load_other(): Specified filename is (null).
- save_jxl(): bytes_per_pixel must be in [0, 2] and less than…
- save_jxl(): JPEG XL only supports at most 4 channels.
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/06b452abc284e340.
Report an issue: GitHub.
Appendix: source
Thrown at ucrop/src/main/jni/CImg.h:70294
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);
}}}}}}
if (!buttons._width)
throw CImgArgumentException("cimg::dialog(): No buttons have been defined.");
cimglist_for(buttons,l) buttons[l].resize(-100,-100,1,3);
unsigned int bw = 0, bh = 0;
cimglist_for(buttons,l) { bw = std::max(bw,buttons[l]._width); bh = std::max(bh,buttons[l]._height); }
bw+=8; bh+=8;
if (bw<64) bw = 64;
if (bw>128) bw = 128;
if (bh<24) bh = 24;
if (bh>48) bh = 48;
CImg<unsigned char> button(bw,bh,1,3);
button.draw_rectangle(0,0,bw - 1,bh - 1,gray);
button.draw_line(0,0,bw - 1,0,white).draw_line(0,bh - 1,0,0,white);
button.draw_line(bw - 1,0,bw - 1,bh - 1,black).draw_line(bw - 1,bh - 1,0,bh - 1,black);
button.draw_line(1,bh - 2,bw - 2,bh - 2,gray2).draw_line(bw - 2,bh - 2,bw - 2,1,gray2);
CImg<unsigned char> sbutton(bw,bh,1,3);
sbutton.draw_rectangle(0,0,bw - 1,bh - 1,gray);
sbutton.draw_line(0,0,bw - 1,0,black).draw_line(bw - 1,0,bw - 1,bh - 1,black);View on GitHub (pinned to f788b534b4)