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
- Use only the declared constants: SwipeableListItem.STATE_CLOSED, STATE_OPEN, STATE_SWIPE_PRIMARY_ACTION.
- Reference constants symbolically (SwipeableListItem.STATE_*) instead of literal numbers so library updates stay compatible.
- 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
- Reference constants symbolically; never persist raw state ints without whitelisting.
- After library upgrades, re-verify constant values used in saved state.
- Annotate internal params with @StableSwipeState to get lint coverage.
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
- Only one RevealableListItem with end gravity is supported.
- Only one RevealableListItem with start gravity is supported.
- Only one SwipeableListItem view is allowed in a ListItemLayo
- No RevealableListItem with gravity {}
- revealView must be a child of ListItemLayout.
AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14).
Data as JSON: /api/errors/10961508a2d9efef.
Report an issue: GitHub.