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

Invalid axis: > axis <

Error message

Invalid axis: > axis <

What it means

MaterialSharedAxis.createPrimaryAnimatorProvider (MaterialSharedAxis.java:116) maps the axis constant to the primary motion: X slides horizontally, Y slides vertically, Z scales. The @Axis annotation allows only X (0), Y (1), Z (2); any other int reaches the default branch and throws IllegalArgumentException when the shared-axis transition is created.

Source

Thrown at lib/java/com/google/android/material/transition/MaterialSharedAxis.java:116

  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

  1. Use MaterialSharedAxis.X, MaterialSharedAxis.Y, or MaterialSharedAxis.Z when constructing the transition.
  2. Validate dynamic axis values: clamp or reject anything outside 0..2.
  3. Annotate your own config-layer parameter with @Axis for lint-time enforcement.

Example fix

// before
MaterialSharedAxis axis = new MaterialSharedAxis(4, true); // invalid

// after
MaterialSharedAxis axis = new MaterialSharedAxis(MaterialSharedAxis.Z, true);
Defensive patterns

Strategy: validation

Validate before calling

static boolean isValidSharedAxis(int axis) {
  return axis == MaterialSharedAxis.X || axis == MaterialSharedAxis.Y || axis == MaterialSharedAxis.Z;
}
if (!isValidSharedAxis(cfgAxis)) throw new IllegalArgumentException("axis must be X, Y or Z");
new MaterialSharedAxis(cfgAxis, true);

Type guard

static @Axis int coerceAxis(int a) {
  return isValidSharedAxis(a) ? a : MaterialSharedAxis.Y;
}

Prevention

When it happens

Trigger: Calling MaterialSharedAxis(MaterialSharedAxis.XYZ_SOMETHING, true) with an invalid int — typically a hardcoded number or a constant imported from the wrong class; constructing MaterialSharedAxis(axis, true) where axis came from serialization/bundles unchecked.

Common situations: Numeric literals instead of MaterialSharedAxis.X/Y/Z; constants mixed up with gravity or fade-mode values; code-generation or JSON-driven transition config that feeds raw ints.

Related errors


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