material-components/material-components-android · error · IllegalArgumentException

Theme overlay should be used with the accompanying int[] att

Error message

Theme overlay should be used with the accompanying int[] attributes.

What it means

HarmonizedColorAttributes couples a theme overlay style with the set of attributes that overlay redefines. Constructing one with a non-zero themeOverlay but an empty attributes array is contradictory (an overlay that harmonizes nothing), so the constructor throws IllegalArgumentException. The public create() overloads normally prevent this; it happens with custom factory paths or reflection.

Source

Thrown at lib/java/com/google/android/material/color/HarmonizedColorAttributes.java:91

   * would:
   *
   * <p>
   *   1. look up the resources values in the theme overlay `Context`.
   *   2. retrieve the harmonized resources with Primary.
   *   3. replace `@color/material_harmonized_color_error`,
   *      `@color/material_harmonized_color_on_error`, etc. with the harmonized resources.
   *
   * <p>That way the Error roles in the theme overlay would point to harmonized resources.
   */
  @NonNull
  public static HarmonizedColorAttributes createMaterialDefaults() {
    return create(HARMONIZED_MATERIAL_ATTRIBUTES, R.style.ThemeOverlay_Material3_HarmonizedColors);
  }

  private HarmonizedColorAttributes(
      @NonNull @AttrRes int[] attributes, @StyleRes int themeOverlay) {
    if (themeOverlay != 0 && attributes.length == 0) {
      throw new IllegalArgumentException(
          "Theme overlay should be used with the accompanying int[] attributes.");
    }
    this.attributes = attributes;
    this.themeOverlay = themeOverlay;
  }

  /** Returns the array of color attributes for harmonization. */
  @NonNull
  public int[] getAttributes() {
    return attributes;
  }

  /** Returns the custom theme overlay for harmonization, default is 0 if not specified. */
  @StyleRes
  public int getThemeOverlay() {
    return themeOverlay;
  }
}

View on GitHub (pinned to ac7e18efee)

Solutions

  1. Pass the actual attributes to harmonize alongside the overlay, or use HarmonizedColorAttributes.createMaterialDefaults().
  2. If attributes are computed dynamically, fall back to create(attrs) with overlay=0 when the list is empty.
  3. Never pair a themeOverlay with an empty attributes array.

Example fix

// before
val attrs = HarmonizedColorAttributes.create(intArrayOf(), R.style.ThemeOverlay_App_Harmonized) // throws

// after
val attrs = if (harmonizeList.isEmpty())
    HarmonizedColorAttributes.createMaterialDefaults()
else
    HarmonizedColorAttributes.create(harmonizeList.toIntArray(), R.style.ThemeOverlay_App_Harmonized)
Defensive patterns

Strategy: validation

Validate before calling

fun buildAttributes(attrs: IntArray, @StyleRes overlay: Int): HarmonizedColorAttributes {
  return if (overlay != 0 && attrs.isEmpty())
    HarmonizedColorAttributes.create(attrs) // overlay 0, no contradiction
  else
    HarmonizedColorAttributes.create(attrs, overlay)
}

Prevention

When it happens

Trigger: Calling create(new int[0], R.style.MyOverlay) or directly constructing HarmonizedColorAttributes with an empty int[] and a non-zero overlay res id; building attributes dynamically from filtered lists that end up empty.

Common situations: Dynamically assembling harmonized attribute lists per feature and passing an empty list when the feature is disabled; copy-pasted custom builders that default to a real overlay style but derive attributes from config.

Related errors


AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14). Data as JSON: /api/errors/0cc96c9602151a24. Report an issue: GitHub.