material-components/material-components-android · error · IllegalArgumentException
Invalid axis: > axis <
Error message
Invalid axis: > axis <
What it means
MaterialSharedAxis builds its primary animator from a fixed @Axis enum whose only legal values are MaterialSharedAxis.X (0), Y (1) and Z (2). createPrimaryAnimatorProvider switches on the axis and any other int falls into the default branch, throwing IllegalArgumentException('Invalid axis: ' + axis). This is a fail-fast guard against typos and against axis values read from theme attributes or serialized state that are not part of the enum.
Source
Thrown at lib/java/com/google/android/material/transition/platform/MaterialSharedAxis.java:121
public int getAxis() {
return axis;
}
public boolean isForward() {
return forward;
}
private static VisibilityAnimatorProvider createPrimaryAnimatorProvider(
@Axis int axis, boolean forward) {
switch (axis) {
case X:
return new SlideDistanceProvider(forward ? Gravity.END : Gravity.START);
case Y:
return new SlideDistanceProvider(forward ? Gravity.BOTTOM : Gravity.TOP);
case Z:
return new ScaleProvider(forward);
default:
throw new IllegalArgumentException("Invalid axis: " + axis);
}
}
private static VisibilityAnimatorProvider createSecondaryAnimatorProvider() {
return new FadeThroughProvider();
}
@AttrRes
@Override
int getDurationThemeAttrResId(boolean appearing) {
return DEFAULT_THEMED_DURATION_ATTR;
}
@AttrRes
@Override
int getEasingThemeAttrResId(boolean appearing) {
return DEFAULT_THEMED_EASING_ATTR;
}View on GitHub (pinned to ac7e18efee)
Solutions
- Pass only the class constants: MaterialSharedAxis.X, MaterialSharedAxis.Y, or MaterialSharedAxis.Z.
- If the axis comes from external input, clamp/map it first: int axis = parseAxis(raw); if (axis < 0 || axis > 2) axis = MaterialSharedAxis.X;
- Check the XML transition definition for a hand-typed axis value and replace it with @enum (linear|arc|... axis enums: 0/1/2) or the corresponding int.
- Verify the value against the @Axis int... annotation contract in the source before constructing the transition.
Example fix
// before
int axis = preferences.getInt("nav_axis", 3); // out of range
transition = new MaterialSharedAxis(getContext(), attr, axis);
// after
int raw = preferences.getInt("nav_axis", MaterialSharedAxis.X);
int axis = (raw >= MaterialSharedAxis.X && raw <= MaterialSharedAxis.Z)
? raw : MaterialSharedAxis.X;
transition = new MaterialSharedAxis(getContext(), attr, axis); Defensive patterns
Strategy: validation
Validate before calling
static final int[] VALID_AXES = {
MaterialSharedAxis.X, MaterialSharedAxis.Y, MaterialSharedAxis.Z};
@MaterialSharedAxis.Axis int sanitizeAxis(int raw) {
for (int valid : VALID_AXES) {
if (raw == valid) return raw;
}
return MaterialSharedAxis.X; // or throw on untrusted input
} Type guard
static boolean isValidAxis(int axis) {
return axis == MaterialSharedAxis.X
|| axis == MaterialSharedAxis.Y
|| axis == MaterialSharedAxis.Z;
} Try / catch
try {
transition = new MaterialSharedAxis(context, attr, axis);
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Invalid axis")) {
transition = new MaterialSharedAxis(context, attr, MaterialSharedAxis.X);
} else {
throw e;
}
} Prevention
- Always construct the axis from MaterialSharedAxis.X/Y/Z constants, never raw ints.
- Treat axes from preferences, deep links, or payloads as untrusted; whitelist them.
- Add a lint/test assert when mapping an enum to the axis int.
When it happens
Trigger: Calling new MaterialSharedAxis(context, attr, axis) or MaterialSharedAxis.create(context, attr, axis) with an int outside 0..2; inflating a transition from XML where the app:transitionMotionPath...-style axis attribute was hand-edited to 3+; computing the axis at runtime from an unchecked config value or deep-link extra and passing it through.
Common situations: Storing the axis in a settings/preferences int and mapping it incorrectly; copy-pasting example code that uses a made-up constant; proguard/R8 shrinking or ordinal misuse (e.g., axis = someEnum.values().length); deserializing the axis from JSON/analytics payloads.
Related errors
- Invalid axis: > axis <
- Slide distance must be positive. If attempting to reverse th
- Invalid slide direction: > slideEdge <
- There must be a keyline marked as focal.
- No color resources provided for harmonization.
AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14).
Data as JSON: /api/errors/b1e1866ce99043dc.
Report an issue: GitHub.