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

  1. Remove the setShadowRadius call from any builder chain that also calls setCircle — circle shadows derive radius from size, not an explicit radius.
  2. If you need both shapes, build two separate Config instances rather than toggling on one.
  3. Reorder logic so setCircle() is chosen instead of setShadowRadius(), never both.
  4. 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

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


AI-assisted analysis of Blankj/AndroidUtilCode@7b4caf9e54 (2026-08-14). Data as JSON: /api/errors/243f107f71c82214. Report an issue: GitHub.