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

Invalid state to get top offset:

Error message

Invalid state to get top offset: 

What it means

BottomSheetBehavior.getTopOffsetForState(int) is an internal helper that maps a stable target state to its pixel top offset (collapsedOffset, expanded offset, halfExpandedOffset, or parentHeight for HIDDEN). Any state outside those four cases falls through the switch and throws IllegalArgumentException with the state value appended.

Source

Thrown at lib/java/com/google/android/material/bottomsheet/BottomSheetBehavior.java:2069

    } else {
      setStateInternal(state);
    }
  }

  private int getTopOffsetForState(@StableState int state) {
    switch (state) {
      case STATE_COLLAPSED:
        return collapsedOffset;
      case STATE_EXPANDED:
        return getExpandedOffset();
      case STATE_HALF_EXPANDED:
        return halfExpandedOffset;
      case STATE_HIDDEN:
        return parentHeight;
      default:
        // Fall through
    }
    throw new IllegalArgumentException("Invalid state to get top offset: " + state);
  }

  private final ViewDragHelper.Callback dragCallback =
      new ViewDragHelper.Callback() {

        private long viewCapturedMillis;

        @Override
        public boolean tryCaptureView(@NonNull View child, int pointerId) {
          if (state == STATE_DRAGGING) {
            return false;
          }
          if (touchingScrollingChild) {
            return false;
          }
          if (state == STATE_EXPANDED && activePointerId == pointerId) {
            View scroll;
            if (multipleScrollingChildrenSupported) {

View on GitHub (pinned to ac7e18efee)

Solutions

  1. Only use the documented constants: STATE_COLLAPSED, STATE_EXPANDED, STATE_HALF_EXPANDED, STATE_HIDDEN (and never DRAGGING/SETTLING via setState).
  2. Validate deserialized state values against the known set before calling setState.
  3. If you must store state as an int, round-trip only values obtained from the STATE_* constants.

Example fix

// before
int state = prefs.getInt("sheet_state", -1);
behavior.setState(state); // -1 -> "Invalid state to get top offset: -1"

// after
int state = prefs.getInt("sheet_state", BottomSheetBehavior.STATE_COLLAPSED);
if (state != STATE_COLLAPSED && state != STATE_EXPANDED
    && state != STATE_HALF_EXPANDED && state != STATE_HIDDEN) {
  state = BottomSheetBehavior.STATE_COLLAPSED;
}
behavior.setState(state);
Defensive patterns

Strategy: validation

Validate before calling

int s = readState();
if (s != STATE_COLLAPSED && s != STATE_EXPANDED && s != STATE_HALF_EXPANDED && s != STATE_HIDDEN) {
  s = BottomSheetBehavior.STATE_COLLAPSED;
}
behavior.setState(s);

Prevention

When it happens

Trigger: Reaching this code via setState with an unexpected int (the setter routes stable states through getTopOffsetForState); internal calls like calculateHalfExpandedOffset when the behavior was constructed with an invalid state constant, e.g. a fabricated int passed instead of a STATE_* constant.

Common situations: Passing a raw int from storage/intent extras into setState without validating it is one of the STATE_* constants; deserializing a corrupted state value; using reflection or custom constants that collide with none of the cases.

Related errors


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