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

cradleVerticalOffset must be positive.

Error message

cradleVerticalOffset must be positive.

What it means

BottomAppBarTopEdgeTreatment.setCradleVerticalOffset(float) defines the vertical offset in pixels of the cradled FloatingActionButton relative to the BottomAppBar's top edge. The treatment only accepts non-negative values (@FloatRange(from = 0f)); a negative offset throws IllegalArgumentException.

Source

Thrown at lib/java/com/google/android/material/bottomappbar/BottomAppBarTopEdgeTreatment.java:233

  }

  /**
   * Returns vertical offset, in pixels, of the {@link FloatingActionButton} being cradled. An
   * offset of 0 indicates the vertical center of the {@link FloatingActionButton} is positioned on
   * the top edge.
   */
  float getCradleVerticalOffset() {
    return cradleVerticalOffset;
  }

  /**
   * Sets the vertical offset, in pixels, of the {@link FloatingActionButton} being cradled. An
   * offset of 0 indicates the vertical center of the {@link FloatingActionButton} is positioned on
   * the top edge.
   */
  void setCradleVerticalOffset(@FloatRange(from = 0f) float cradleVerticalOffset) {
    if (cradleVerticalOffset < 0) {
      throw new IllegalArgumentException("cradleVerticalOffset must be positive.");
    }
    this.cradleVerticalOffset = cradleVerticalOffset;
  }

  float getFabCradleMargin() {
    return fabMargin;
  }

  void setFabCradleMargin(float fabMargin) {
    this.fabMargin = fabMargin;
  }

  float getFabCradleRoundedCornerRadius() {
    return roundedCornerRadius;
  }

  void setFabCradleRoundedCornerRadius(float roundedCornerRadius) {
    this.roundedCornerRadius = roundedCornerRadius;

View on GitHub (pinned to ac7e18efee)

Solutions

  1. Clamp the value to Math.max(0f, offset) before calling setCradleVerticalOffset.
  2. Fix the source calculation so it cannot produce a negative offset (recheck the sign/direction of the math).
  3. If animating, use Animator.setEvaluator or an ArgbEvaluator-equivalent clamping approach so intermediate values stay >= 0.

Example fix

// before
float offset = computedOffset; // may be negative
bottomAppBarTopEdgeTreatment.setCradleVerticalOffset(offset);

// after
bottomAppBarTopEdgeTreatment.setCradleVerticalOffset(Math.max(0f, computedOffset));
Defensive patterns

Strategy: validation

Validate before calling

float safeOffset = Math.max(0f, computedCradleOffset);
topEdgeTreatment.setCradleVerticalOffset(safeOffset);

Prevention

When it happens

Trigger: Calling setCradleVerticalOffset with a negative float; reading a value from dimension resources, animations, or user input that computes to < 0 and passing it through; deriving the offset from a scroll position that can go negative.

Common situations: Animators that interpolate the offset and briefly produce negative interpolated values; binding the offset to a calculation like (anchorY - fabY) that flips sign on small screens; migrating from an older version where negative offsets were silently clamped.

Related errors


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