{"record":{"id":"d7f3509f59083720","repo":"material-components/material-components-android","slug":"custom-size-must-be-non-negative","errorCode":null,"errorMessage":"Custom size must be non-negative","messagePattern":"Custom size must be non-negative","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"lib/java/com/google/android/material/floatingactionbutton/FloatingActionButton.java","lineNumber":809,"sourceCode":"  }\n\n  public boolean isOrWillBeShown() {\n    return getImpl().isOrWillBeShown();\n  }\n\n  /**\n   * Sets the size of the button to be a custom value in pixels.\n   *\n   * <p>If you've set a custom size and would like to clear it, you can use the {@link\n   * #clearCustomSize()} method. If called, custom sizing will not be used and the size will be\n   * calculated based on the value set using {@link #setSize(int)} or the {@code fabSize} attribute.\n   *\n   * @param size preferred size in pixels, or {@link #NO_CUSTOM_SIZE}\n   * @attr ref com.google.android.material.R.styleable#FloatingActionButton_fabCustomSize\n   */\n  public void setCustomSize(@Px int size) {\n    if (size < 0) {\n      throw new IllegalArgumentException(\"Custom size must be non-negative\");\n    }\n\n    if (size != customSize) {\n      customSize = size;\n      requestLayout();\n    }\n  }\n\n  /**\n   * Returns the custom size for this {@link FloatingActionButton}.\n   *\n   * @return size in pixels, or {@link #NO_CUSTOM_SIZE}\n   */\n  @Px\n  public int getCustomSize() {\n    return customSize;\n  }\n","sourceCodeStart":791,"sourceCodeEnd":827,"githubUrl":"https://github.com/material-components/material-components-android/blob/ac7e18efeefb331850c561faf9ab8bf81d27ba68/lib/java/com/google/android/material/floatingactionbutton/FloatingActionButton.java#L791-L827","documentation":"FloatingActionButton.setCustomSize(@Px int size) sets an explicit pixel size for the FAB. Only zero (FloatingActionButton.NO_CUSTOM_SIZE, meaning 'no custom size') or positive values are legal; a negative size cannot produce a valid measurement so the method throws IllegalArgumentException.","triggerScenarios":"Passing a negative pixel value, e.g. setCustomSize(-1) used as a sentinel by app code; computing size from a dimension difference that can go negative (padding larger than requested size); unboxing an Integer/nullable boxed value that defaults to -1 when absent from config.","commonSituations":"Using -1 as 'not set' sentinel then forwarding it directly to setCustomSize; resizing FABs responsively (screen width minus margins) on small screens or multi-window where the calculation underflows; data-driven UI where size comes from a backend/JSON field.","solutions":["Normalize before calling: if (size > 0) fab.setCustomSize(size) else fab.clearCustomSize();","Never use negative sentinels; use FloatingActionButton.NO_CUSTOM_SIZE (0) or a nullable Integer checked for null.","Clamp computed sizes: Math.max(0, computedSizePx) and confirm dimension math cannot underflow on the smallest supported screens."],"exampleFix":"// before\nint size = prefs.getInt(\"fab_size\", -1);\nfab.setCustomSize(size); // -1 -> IllegalArgumentException\n\n// after\nint size = prefs.getInt(\"fab_size\", FloatingActionButton.NO_CUSTOM_SIZE);\nif (size > 0) {\n  fab.setCustomSize(size);\n} else {\n  fab.clearCustomSize();\n}","handlingStrategy":"validation","validationCode":"if (size > 0) {\n  fab.setCustomSize(size);\n} else {\n  fab.clearCustomSize();\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use FloatingActionButton.NO_CUSTOM_SIZE (0) as the 'unset' sentinel, never -1.","Clamp computed pixel sizes with Math.max(0, value) before calling setCustomSize.","Validate backend/config-provided sizes at the data layer boundary."],"tags":["material-components","fab","size","validation"],"backgroundTag":null,"analyzedSha":"ac7e18efeefb331850c561faf9ab8bf81d27ba68","analyzedAt":"2026-08-14T15:35:35.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}