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

Invalid state to get swipe offset: {}

Error message

Invalid state to get swipe offset: {}

What it means

Inside getOffsetForSwipeState, after the gravity check, a switch maps the swipe state to an offset: STATE_CLOSED, STATE_OPEN, or STATE_SWIPE_PRIMARY_ACTION. Any other int reaches the default branch and throws IllegalArgumentException with the offending value — this guards against unknown/invalid state constants reaching internal offset math.

Source

Thrown at lib/java/com/google/android/material/listitem/ListItemLayout.java:701

    } else {
      return swipeToRevealLayoutRight instanceof RevealableListItem;
    }
  }

  private int getOffsetForSwipeState(
      @StableSwipeState int swipeState, @RevealGravity int revealGravity) {
    if (!swipeToRevealLayoutExistsForGravity(revealGravity)) {
      throw new IllegalArgumentException("No RevealableListItem with gravity " + revealGravity);
    }
    switch (swipeState) {
      case STATE_CLOSED:
        return getSwipeViewClosedOffset();
      case STATE_OPEN:
        return getSwipeRevealViewRevealedOffset(revealGravity);
      case STATE_SWIPE_PRIMARY_ACTION:
        return getSwipeToActionOffset(revealGravity);
      default:
        throw new IllegalArgumentException("Invalid state to get swipe offset: " + swipeState);
    }
  }

  private void updateSwipeProgress(int left) {
    if (!(contentView instanceof SwipeableListItem && swipeToRevealLayoutExists())) {
      return;
    }
    revealViewOffset = left - originalContentViewLeft;
    boolean revealingLeft = revealViewOffset > 0;
    boolean revealingRight = revealViewOffset < 0;

    // Update the activeSwipeToRevealLayout
    if (revealingLeft && swipeToRevealLayoutLeft instanceof RevealableListItem) {
      activeSwipeToRevealLayout = (RevealableListItem) swipeToRevealLayoutLeft;
    } else if (revealingRight && swipeToRevealLayoutRight instanceof RevealableListItem) {
      activeSwipeToRevealLayout = (RevealableListItem) swipeToRevealLayoutRight;
    }

View on GitHub (pinned to ac7e18efee)

Solutions

  1. Use only the declared constants: SwipeableListItem.STATE_CLOSED, STATE_OPEN, STATE_SWIPE_PRIMARY_ACTION.
  2. Reference constants symbolically (SwipeableListItem.STATE_*) instead of literal numbers so library updates stay compatible.
  3. If persisting state across process restarts, map stored values through a whitelist to the current constants before use.

Example fix

// before
listItemLayout.setSwipeState(2 /* hardcoded from old sample */, gravity, true);

// after
listItemLayout.setSwipeState(SwipeableListItem.STATE_SWIPE_PRIMARY_ACTION, gravity, true);
Defensive patterns

Strategy: validation

Validate before calling

static boolean isValidSwipeState(int s) {
  return s == SwipeableListItem.STATE_CLOSED
      || s == SwipeableListItem.STATE_OPEN
      || s == SwipeableListItem.STATE_SWIPE_PRIMARY_ACTION;
}
if (!isValidSwipeState(state)) state = SwipeableListItem.STATE_CLOSED;

Prevention

When it happens

Trigger: Passing a raw int or a stale constant from a different class (e.g. a copied constant whose value changed between library versions) as swipeState; subclass or reflection code invoking the internal method with an arbitrary value.

Common situations: Version upgrades where state constant values changed; mixing app-defined state ints with SwipeableListItem states; copying sample code from an older library revision.

Related errors


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