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

  1. Pass only the class constants: MaterialSharedAxis.X, MaterialSharedAxis.Y, or MaterialSharedAxis.Z.
  2. If the axis comes from external input, clamp/map it first: int axis = parseAxis(raw); if (axis < 0 || axis > 2) axis = MaterialSharedAxis.X;
  3. 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.
  4. 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

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


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