material-components/material-components-android · error · IllegalArgumentException
No color resources provided for harmonization.
Error message
No color resources provided for harmonization.
What it means
ColorResourcesTableCreator.create(context, colorMapping) builds a runtime resources table (arsc blob) for color harmonization/override. An empty mapping means there is nothing to write, so the method fails fast with IllegalArgumentException rather than producing a broken table. Callers reach it via DynamicColors/DynamicColorsOptions with harmonized or color override maps.
Source
Thrown at lib/java/com/google/android/material/color/ColorResourcesTableCreator.java:70
private static final String RESOURCE_TYPE_NAME_COLOR = "color";
private static byte typeIdColor;
private static final PackageInfo ANDROID_PACKAGE_INFO =
new PackageInfo(ANDROID_PACKAGE_ID, "android");
private static final Comparator<ColorResource> COLOR_RESOURCE_COMPARATOR =
new Comparator<ColorResource>() {
@Override
public int compare(ColorResource res1, ColorResource res2) {
return res1.entryId - res2.entryId;
}
};
static byte[] create(Context context, Map<Integer, Integer> colorMapping) throws IOException {
if (colorMapping.entrySet().isEmpty()) {
throw new IllegalArgumentException("No color resources provided for harmonization.");
}
PackageInfo applicationPackageInfo =
new PackageInfo(APPLICATION_PACKAGE_ID, context.getPackageName());
Map<PackageInfo, List<ColorResource>> colorResourceMap = new HashMap<>();
ColorResource colorResource = null;
for (Map.Entry<Integer, Integer> entry : colorMapping.entrySet()) {
colorResource =
new ColorResource(
entry.getKey(),
context.getResources().getResourceEntryName(entry.getKey()),
entry.getValue());
if (!context
.getResources()
.getResourceTypeName(entry.getKey())
.equals(RESOURCE_TYPE_NAME_COLOR)) {
throw new IllegalArgumentException(
"Non color resource found: name="View on GitHub (pinned to ac7e18efee)
Solutions
- Skip the harmonization/override call entirely when the map is empty: if (colorMapping.isEmpty()) return.
- Ensure the code building the color override map always adds the intended color resources.
- If using DynamicColors, only enable colorOverrideToResourceIds/DynamicColorsOptions when at least one override exists.
Example fix
// before
ColorResourcesTableCreator.create(context, emptyMap()) // throws
// after
if (colorMapping.isNotEmpty()) {
ColorResourcesTableCreator.create(context, colorMapping)
} Defensive patterns
Strategy: validation
Validate before calling
fun applyHarmonization(context: Context, colorMapping: Map<Int, Int>) {
if (colorMapping.isEmpty()) return // guard: nothing to harmonize
ColorResourcesTableCreator.create(context, colorMapping)
} Prevention
- Check map emptiness before any dynamic-color override call.
- Log when theming config resolves to zero overrides; it usually indicates a config bug.
- Build override maps from typed resource constants, not free-form config.
When it happens
Trigger: Calling ColorResourcesTableCreator.create(context, emptyMap()) directly; passing DynamicColorsOptions built with an empty colorOverride or colorOverrideMap; filtering a color map down to empty before applying dynamic colors.
Common situations: Feature-flagged theming where the override map is built from server config and comes back empty; generic 'apply overrides' helpers that forward whatever map they receive.
Related errors
- Non color resource found: name={name}, typeId={typeId}
- Not supported with unknown package id: {packageId}
- No color resources found for harmonization.
- Theme overlay should be used with the accompanying int[] att
- There must be a keyline marked as focal.
AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14).
Data as JSON: /api/errors/1419d2420560f4ff.
Report an issue: GitHub.