{"record":{"id":"188d10e8dd52d1b8","repo":"material-components/material-components-android","slug":"invalid-transition-direction-transitiondirectio-188d10","errorCode":null,"errorMessage":"Invalid transition direction: > transitionDirection <","messagePattern":"Invalid transition direction: > transitionDirection <","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"lib/java/com/google/android/material/transition/platform/MaterialContainerTransform.java","lineNumber":1046,"sourceCode":"    if (boundingView != null) {\n      RectF drawableBounds = getLocationInWindow(boundingView);\n      drawableBounds.offset(offsetX, offsetY);\n      return drawableBounds;\n    } else {\n      return new RectF(0, 0, drawingView.getWidth(), drawingView.getHeight());\n    }\n  }\n\n  private boolean isEntering(@NonNull RectF startBounds, @NonNull RectF endBounds) {\n    switch (transitionDirection) {\n      case TRANSITION_DIRECTION_AUTO:\n        return calculateArea(endBounds) > calculateArea(startBounds);\n      case TRANSITION_DIRECTION_ENTER:\n        return true;\n      case TRANSITION_DIRECTION_RETURN:\n        return false;\n      default:\n        throw new IllegalArgumentException(\"Invalid transition direction: \" + transitionDirection);\n    }\n  }\n\n  private ProgressThresholdsGroup buildThresholdsGroup(boolean entering) {\n    PathMotion pathMotion = getPathMotion();\n    if (pathMotion instanceof ArcMotion || pathMotion instanceof MaterialArcMotion) {\n      return getThresholdsOrDefault(\n          entering, DEFAULT_ENTER_THRESHOLDS_ARC, DEFAULT_RETURN_THRESHOLDS_ARC);\n    } else {\n      return getThresholdsOrDefault(entering, DEFAULT_ENTER_THRESHOLDS, DEFAULT_RETURN_THRESHOLDS);\n    }\n  }\n\n  private ProgressThresholdsGroup getThresholdsOrDefault(\n      boolean entering,\n      ProgressThresholdsGroup defaultEnterThresholds,\n      ProgressThresholdsGroup defaultReturnThresholds) {\n    ProgressThresholdsGroup defaultThresholds =","sourceCodeStart":1028,"sourceCodeEnd":1064,"githubUrl":"https://github.com/material-components/material-components-android/blob/ac7e18efeefb331850c561faf9ab8bf81d27ba68/lib/java/com/google/android/material/transition/platform/MaterialContainerTransform.java#L1028-L1064","documentation":"Platform-package copy of the direction check in transition/platform/MaterialContainerTransform.java:1046. isEntering() interprets setTransitionDirection(): AUTO compares start/end areas, ENTER forces entering, RETURN forces return; any other int throws IllegalArgumentException when the transition computes its direction at draw/setup time — which may be later than the setter call.","triggerScenarios":"Calling setTransitionDirection() with an invalid int on the platform MaterialContainerTransform; the crash surfacing only when the transition actually runs (direction is evaluated lazily in isEntering); persisted direction ints restored without validation.","commonSituations":"Hardcoded direction ints; values shared between androidx and platform transform variants; late crash confusing developers because the bad value was set much earlier.","solutions":["Use TRANSITION_DIRECTION_AUTO / TRANSITION_DIRECTION_ENTER / TRANSITION_DIRECTION_RETURN from the platform class.","Sanitize restored or remote values immediately: default to TRANSITION_DIRECTION_AUTO on mismatch.","Validate at set-time in a wrapper so the failure points at the culprit code, not at transition runtime."],"exampleFix":"// before\ntransform.setTransitionDirection(-1);\n\n// after\ntransform.setTransitionDirection(MaterialContainerTransform.TRANSITION_DIRECTION_RETURN);","handlingStrategy":"validation","validationCode":"import com.google.android.material.transition.platform.MaterialContainerTransform;\n\nstatic int coercePlatformDirection(int d) {\n  return (d == MaterialContainerTransform.TRANSITION_DIRECTION_AUTO\n       || d == MaterialContainerTransform.TRANSITION_DIRECTION_ENTER\n       || d == MaterialContainerTransform.TRANSITION_DIRECTION_RETURN)\n      ? d : MaterialContainerTransform.TRANSITION_DIRECTION_AUTO;\n}\ntransform.setTransitionDirection(coercePlatformDirection(restoredDir));","typeGuard":"static boolean isValidPlatformDirection(int d) {\n  return d == MaterialContainerTransform.TRANSITION_DIRECTION_AUTO\n      || d == MaterialContainerTransform.TRANSITION_DIRECTION_ENTER\n      || d == MaterialContainerTransform.TRANSITION_DIRECTION_RETURN;\n}","tryCatchPattern":null,"preventionTips":["Validate direction at set-time because the throw happens lazily in isEntering().","Use TRANSITION_DIRECTION_* constants from the platform variant.","Default to AUTO when restoring untrusted values."],"tags":["android","material-components","platform-transitions","container-transform","transition-direction","enum-validation"],"backgroundTag":null,"analyzedSha":"ac7e18efeefb331850c561faf9ab8bf81d27ba68","analyzedAt":"2026-08-14T15:35:35.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}