{"record":{"id":"f9afc87538123f94","repo":"material-components/material-components-android","slug":"invalid-slide-direction-slideedge-f9afc8","errorCode":null,"errorMessage":"Invalid slide direction: > slideEdge <","messagePattern":"Invalid slide direction: > slideEdge <","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"lib/java/com/google/android/material/transition/platform/SlideDistanceProvider.java","lineNumber":157,"sourceCode":"        return createTranslationYAnimator(view, originalY - slideDistance, originalY, originalY);\n      case Gravity.RIGHT:\n        return createTranslationXAnimator(view, originalX - slideDistance, originalX, originalX);\n      case Gravity.BOTTOM:\n        return createTranslationYAnimator(view, originalY + slideDistance, originalY, originalY);\n      case Gravity.START:\n        return createTranslationXAnimator(\n            view,\n            isRtl(sceneRoot) ? originalX + slideDistance : originalX - slideDistance,\n            originalX,\n            originalX);\n      case Gravity.END:\n        return createTranslationXAnimator(\n            view,\n            isRtl(sceneRoot) ? originalX - slideDistance : originalX + slideDistance,\n            originalX,\n            originalX);\n      default:\n        throw new IllegalArgumentException(\"Invalid slide direction: \" + slideEdge);\n    }\n  }\n\n  private static Animator createTranslationDisappearAnimator(\n      View sceneRoot, View view, @GravityFlag int slideEdge, @Px int slideDistance) {\n    final float originalX = view.getTranslationX();\n    final float originalY = view.getTranslationY();\n    switch (slideEdge) {\n      case Gravity.LEFT:\n        return createTranslationXAnimator(view, originalX, originalX - slideDistance, originalX);\n      case Gravity.TOP:\n        return createTranslationYAnimator(view, originalY, originalY + slideDistance, originalY);\n      case Gravity.RIGHT:\n        return createTranslationXAnimator(view, originalX, originalX + slideDistance, originalX);\n      case Gravity.BOTTOM:\n        return createTranslationYAnimator(view, originalY, originalY - slideDistance, originalY);\n      case Gravity.START:\n        return createTranslationXAnimator(","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/material-components/material-components-android/blob/ac7e18efeefb331850c561faf9ab8bf81d27ba68/lib/java/com/google/android/material/transition/platform/SlideDistanceProvider.java#L139-L175","documentation":"When a SlideDistanceProvider appear-animation starts, createTranslationAppearAnimator switches on the configured slideEdge and supports only Gravity.LEFT, TOP, RIGHT, BOTTOM, START and END. Any other gravity flag (single unsupported values like Gravity.CENTER, or composite/bitmask flags such as Gravity.CENTER_VERTICAL, Gravity.FILL, TOP|START) misses every case and hits the default branch, throwing IllegalArgumentException('Invalid slide direction: ' + slideEdge).","triggerScenarios":"Calling setSlideEdge(Gravity.CENTER), Gravity.NO_GRAVITY (0), Gravity.FILL, or a combined bitmask like Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL on a SlideDistanceProvider/MaterialSharedAxis-style provider; reusing a gravity constant parsed from XML (android:gravity values) without narrowing it to an edge.","commonSituations":"Copy-pasting a layout's android:gravity (e.g., center) into setSlideEdge; storing the slide edge in preferences as a generic gravity int; refactoring from a side-drawer gravity that uses composite flags; Gravity.NO_GRAVITY leaking through when a binding is unset.","solutions":["Pass one of the six supported edge constants: Gravity.LEFT, Gravity.TOP, Gravity.RIGHT, Gravity.BOTTOM, Gravity.START or Gravity.END.","If the value comes from config, validate it against a whitelist before calling setSlideEdge (see validationCode).","Normalize composite gravities first with Gravity.absoluteGravityValue / by extracting a single edge, instead of forwarding the raw flag.","Prefer START/END over LEFT/RIGHT so RTL layouts slide correctly."],"exampleFix":"// before\nprovider.setSlideEdge(Gravity.CENTER); // throws on createAppear\n\n// after\nprovider.setSlideEdge(Gravity.END);","handlingStrategy":"type-guard","validationCode":"static final Set<Integer> SUPPORTED_EDGES = new HashSet<>(Arrays.asList(\n    Gravity.LEFT, Gravity.TOP, Gravity.RIGHT, Gravity.BOTTOM,\n    Gravity.START, Gravity.END));\n\nint normalizeSlideEdge(int edge) {\n  return SUPPORTED_EDGES.contains(edge) ? edge : Gravity.END; // sane default\n}","typeGuard":"static boolean isSupportedSlideEdge(@GravityFlag int edge) {\n  return edge == Gravity.LEFT || edge == Gravity.TOP || edge == Gravity.RIGHT\n      || edge == Gravity.BOTTOM || edge == Gravity.START || edge == Gravity.END;\n}","tryCatchPattern":null,"preventionTips":["Never forward a composite android:gravity bitmask into setSlideEdge — pick a single edge.","Whitelist edges from configs/prefs with isSupportedSlideEdge before applying.","Note Gravity.CENTER and Gravity.NO_GRAVITY are NOT slide edges.","Test the enter animation after any edge change; the throw happens at animator creation."],"tags":["android","material-components","transition","gravity","validation"],"backgroundTag":null,"analyzedSha":"ac7e18efeefb331850c561faf9ab8bf81d27ba68","analyzedAt":"2026-08-14T15:35:35.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}