{"record":{"id":"06b452abc284e340","repo":"Yalantis/uCrop","slug":"cimg-dialog-no-buttons-have-been-defined","errorCode":null,"errorMessage":"cimg::dialog(): No buttons have been defined.","messagePattern":"cimg::dialog\\(\\): No buttons have been defined\\.","errorType":"exception","errorClass":"CImgArgumentException","httpStatus":null,"severity":"error","filePath":"ucrop/src/main/jni/CImg.h","lineNumber":70294,"sourceCode":"        black[] = { 0,0,0 }, white[] = { 255,255,255 }, gray[] = { 200,200,200 }, gray2[] = { 150,150,150 };\n\n      // Create buttons and canvas graphics.\n      CImgList<unsigned char> buttons, cbuttons, sbuttons;\n      if (button1_label) {\n        CImg<unsigned char>().draw_text(0,0,button1_label,black,gray,1,13).move_to(buttons);\n        if (button2_label) {\n          CImg<unsigned char>().draw_text(0,0,button2_label,black,gray,1,13).move_to(buttons);\n          if (button3_label) {\n            CImg<unsigned char>().draw_text(0,0,button3_label,black,gray,1,13).move_to(buttons);\n            if (button4_label) {\n              CImg<unsigned char>().draw_text(0,0,button4_label,black,gray,1,13).move_to(buttons);\n              if (button5_label) {\n                CImg<unsigned char>().draw_text(0,0,button5_label,black,gray,1,13).move_to(buttons);\n                if (button6_label) {\n                  CImg<unsigned char>().draw_text(0,0,button6_label,black,gray,1,13).move_to(buttons);\n                }}}}}}\n      if (!buttons._width)\n        throw CImgArgumentException(\"cimg::dialog(): No buttons have been defined.\");\n      cimglist_for(buttons,l) buttons[l].resize(-100,-100,1,3);\n\n      unsigned int bw = 0, bh = 0;\n      cimglist_for(buttons,l) { bw = std::max(bw,buttons[l]._width); bh = std::max(bh,buttons[l]._height); }\n      bw+=8; bh+=8;\n      if (bw<64) bw = 64;\n      if (bw>128) bw = 128;\n      if (bh<24) bh = 24;\n      if (bh>48) bh = 48;\n\n      CImg<unsigned char> button(bw,bh,1,3);\n      button.draw_rectangle(0,0,bw - 1,bh - 1,gray);\n      button.draw_line(0,0,bw - 1,0,white).draw_line(0,bh - 1,0,0,white);\n      button.draw_line(bw - 1,0,bw - 1,bh - 1,black).draw_line(bw - 1,bh - 1,0,bh - 1,black);\n      button.draw_line(1,bh - 2,bw - 2,bh - 2,gray2).draw_line(bw - 2,bh - 2,bw - 2,1,gray2);\n      CImg<unsigned char> sbutton(bw,bh,1,3);\n      sbutton.draw_rectangle(0,0,bw - 1,bh - 1,gray);\n      sbutton.draw_line(0,0,bw - 1,0,black).draw_line(bw - 1,0,bw - 1,bh - 1,black);","sourceCodeStart":70276,"sourceCodeEnd":70312,"githubUrl":"https://github.com/Yalantis/uCrop/blob/f788b534b48c144edf786c8cddbf0e029e637804/ucrop/src/main/jni/CImg.h#L70276-L70312","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ncimg::dialog(\"Load error\", \"Cannot open file\", NULL, NULL, NULL, NULL, NULL, NULL); // no buttons -> throws\n// after\nif (buttonLabels.empty()) buttonLabels.push_back(\"OK\");\ncimg::dialog(\"Load error\", \"Cannot open file\", buttonLabels[0],\n             buttonLabels.size()>1?buttonLabels[1].c_str():NULL,\n             buttonLabels.size()>2?buttonLabels[2].c_str():NULL,\n             NULL, NULL, NULL);","handlingStrategy":"validation","validationCode":"// Require at least one non-null button label before opening a dialog\nbool hasButton(const char* b1, const char* b2, const char* b3,\n               const char* b4, const char* b5, const char* b6) {\n  return b1 || b2 || b3 || b4 || b5 || b6;\n}\nif (hasButton(b1,b2,b3,b4,b5,b6)) {\n  cimg::dialog(title, msg, b1?b1:\"\", b2, b3, b4, b5, b6);\n} else {\n  cimg::dialog(title, msg, \"OK\", NULL, NULL, NULL, NULL, NULL); // default button\n}","typeGuard":null,"tryCatchPattern":"try {\n  cimg::dialog(title, msg, b1, b2, b3, b4, b5, b6);\n} catch (CImgArgumentException& e) {\n  std::cerr << \"Dialog error: \" << e.what() << \"\\n\";\n  cimg::dialog(title, msg, \"OK\", NULL, NULL, NULL, NULL, NULL); // retry with default\n}","preventionTips":["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."],"tags":["gui","dialog","missing-argument","validation","cimg"],"backgroundTag":"missing-required-argument","analyzedSha":"f788b534b48c144edf786c8cddbf0e029e637804","analyzedAt":"2026-09-08T08:36:04.887Z","contentChangedAt":"2026-09-08T08:36:04.887Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}