Blankj/AndroidUtilCode · error · IllegalArgumentException
Set circle needn't set radius.
Error message
Set circle needn't set radius.
What it means
ShadowUtils.Config.setShadowRadius stores the radius and then throws IllegalArgumentException if isCircle is already true. The builder enforces a mutual-exclusion contract: a circular shadow has no meaningful radius, so once setCircle() has been called, supplying a radius is a configuration error. The throw happens AFTER the field is written, signalling the caller violated the intended build order.
Source
Thrown at lib/utilcode/src/main/java/com/blankj/utilcode/util/ShadowUtils.java:78
private static final int SHADOW_COLOR_DEFAULT = 0x44000000;
private static final int SHADOW_SIZE = UtilsBridge.dp2px(8);
private float mShadowRadius = -1;
private float mShadowSizeNormal = -1;
private float mShadowSizePressed = -1;
private float mShadowMaxSizeNormal = -1;
private float mShadowMaxSizePressed = -1;
private int mShadowColorNormal = SHADOW_COLOR_DEFAULT;
private int mShadowColorPressed = SHADOW_COLOR_DEFAULT;
private boolean isCircle = false;
public Config() {
}
public Config setShadowRadius(float radius) {
this.mShadowRadius = radius;
if (isCircle) {
throw new IllegalArgumentException("Set circle needn't set radius.");
}
return this;
}
public Config setCircle() {
isCircle = true;
if (mShadowRadius != -1) {
throw new IllegalArgumentException("Set circle needn't set radius.");
}
return this;
}
public Config setShadowSize(int size) {
return setShadowSize(size, size);
}
public Config setShadowSize(int sizeNormal, int sizePressed) {
this.mShadowSizeNormal = sizeNormal;View on GitHub (pinned to 7b4caf9e54)
Solutions
- Remove the setShadowRadius call from any builder chain that also calls setCircle — circle shadows derive radius from size, not an explicit radius.
- If you need both shapes, build two separate Config instances rather than toggling on one.
- Reorder logic so setCircle() is chosen instead of setShadowRadius(), never both.
- Audit the build chain end-to-end before apply() to ensure only one of the two is set.
Example fix
// before
new ShadowUtils.Config()
.setCircle()
.setShadowRadius(8) // throws
...
// after
new ShadowUtils.Config()
.setCircle()
.setShadowSize(8)
... Defensive patterns
Strategy: validation
Validate before calling
// Validate build intent before constructing the Config chain.
boolean useCircle = /* ... */;
if (useCircle) {
// do NOT call setShadowRadius; use setShadowSize only
} else {
// call setShadowRadius, do NOT call setCircle
} Try / catch
try {
config.setShadowRadius(r);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("circle")) { /* radius not valid for circle; ignore or log */ }
else throw e;
} Prevention
- Decide circle vs rectangular shadow before building the Config.
- Never chain both setCircle and setShadowRadius on the same Config.
- Centralize shadow Config construction in one factory method per shape.
- Add a unit test covering each shape variant.
When it happens
Trigger: Calling new ShadowUtils.Config().setCircle().setShadowRadius(x) — the radius call throws because isCircle is already true. Any build sequence where setCircle() precedes setShadowRadius() triggers it.
Common situations: Copy-pasting config code that chained setShadowRadius for a rectangular shadow and then flipping to setCircle; conditional builder logic that sets radius in one branch and circle in another; refactor where setCircle was added late without removing the radius call.
Related errors
- invalid shadow size
- onCreateViewHolder: get holder from view type failed.
- comparator must not be null
- {}
- segment of <{segment}> is illegal
AI-assisted analysis of Blankj/AndroidUtilCode@7b4caf9e54 (2026-08-14).
Data as JSON: /api/errors/243f107f71c82214.
Report an issue: GitHub.