material-components/material-components-android · error · IllegalStateException
Unexpected value: %s
Error message
Unexpected value: %s
What it means
SideSheetBehavior's saved-state offset calculation throws IllegalStateException for a state outside {STATE_EXPANDED, STATE_DRAGGING, STATE_SETTLING, STATE_HIDDEN}. The switch has no default handling for other ints, which almost always means a corrupted or hand-constructed saved-state / unstable state value rather than normal library flow.
Source
Thrown at lib/java/com/google/android/material/sidesheet/SideSheetBehavior.java:469
return innerMargin;
}
private int calculateCurrentOffset(int savedOuterEdge, V child) {
int currentOffset;
switch (state) {
case STATE_EXPANDED:
currentOffset = 0;
break;
case STATE_DRAGGING:
case STATE_SETTLING:
currentOffset = savedOuterEdge - sheetDelegate.getOuterEdge(child);
break;
case STATE_HIDDEN:
currentOffset = sheetDelegate.getHiddenOffset();
break;
default:
throw new IllegalStateException("Unexpected value: " + state);
}
return currentOffset;
}
@Override
public boolean onInterceptTouchEvent(
@NonNull CoordinatorLayout parent, @NonNull V child, @NonNull MotionEvent event) {
if (!shouldInterceptTouchEvent(child)) {
ignoreEvents = true;
return false;
}
int action = event.getActionMasked();
// Record the velocity
if (action == MotionEvent.ACTION_DOWN) {
resetVelocity();
}
if (velocityTracker == null) {
velocityTracker = VelocityTracker.obtain();View on GitHub (pinned to ac7e18efee)
Solutions
- Only ever set states via setState(STATE_EXPANDED / STATE_HIDDEN) and let the library persist its own SavedState.
- If you persist state yourself, store only stable states and rehydrate by calling setState() with a valid constant.
- For tests, use the library's constants instead of raw ints.
Example fix
// before
outState.putInt("sheet_state", currentCustomStateInt); // may hold invalid value
...
behavior.setState(restoredInt);
// after
outState.putBoolean("sheet_expanded", behavior.getState() == BottomSheetBehavior.STATE_EXPANDED);
...
behavior.setState(restoredExpanded ? BottomSheetBehavior.STATE_EXPANDED
: BottomSheetBehavior.STATE_HIDDEN); Defensive patterns
Strategy: validation
Validate before calling
static boolean isKnownSheetState(int state) {
return state == BottomSheetBehavior.STATE_EXPANDED
|| state == BottomSheetBehavior.STATE_DRAGGING
|| state == BottomSheetBehavior.STATE_SETTLING
|| state == BottomSheetBehavior.STATE_HIDDEN;
} Prevention
- Let the behavior save/restore its own SavedState instead of hand-parceling state ints.
- When persisting manually, store booleans or enum names, then map to library constants on restore.
When it happens
Trigger: Restoring a SideSheetBehavior.SavedState written with parceling bugs, or calling internal state APIs with an arbitrary int; also reachable from code that writes STATE_DRAGGING-like custom constants into the behavior's state.
Common situations: Custom Parcelable for a screen that manually serializes sheet state and deserializes an invalid int; process-death restore where a stale version of the saved state format is read; reflective or state-injection tricks used in tests.
Related errors
- Sheet view reference is null; sheet edge cannot be changed i
- Sheet view has been laid out; sheet edge cannot be changed o
- Invalid sheet edge position value: %d. Must be %d or %d.
- STATE_%s should not be set externally.
- Invalid state to get outer edge offset: %d
AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14).
Data as JSON: /api/errors/cc47436560d4e095.
Report an issue: GitHub.