{"record":{"id":"9d538e3be093308f","repo":"material-components/material-components-android","slug":"motion-path-theme-attribute-must-either-be-an-enum-9d538e","errorCode":null,"errorMessage":"Motion path theme attribute must either be an enum value or path data string","messagePattern":"Motion path theme attribute must either be an enum value or path data string","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"lib/java/com/google/android/material/transition/platform/TransitionUtils.java","lineNumber":119,"sourceCode":"  @Nullable\n  static PathMotion resolveThemePath(Context context, @AttrRes int attrResId) {\n    TypedValue pathValue = new TypedValue();\n    if (context.getTheme().resolveAttribute(attrResId, pathValue, true)) {\n      if (pathValue.type == TypedValue.TYPE_INT_DEC) {\n        int pathInt = pathValue.data;\n        if (pathInt == PATH_TYPE_LINEAR) {\n          // Default Transition PathMotion is linear; no need to override with different PathMotion.\n          return null;\n        } else if (pathInt == PATH_TYPE_ARC) {\n          return new MaterialArcMotion();\n        } else {\n          throw new IllegalArgumentException(\"Invalid motion path type: \" + pathInt);\n        }\n      } else if (pathValue.type == TypedValue.TYPE_STRING) {\n        String pathString = String.valueOf(pathValue.string);\n        return new PatternPathMotion(PathParser.createPathFromPathData(pathString));\n      } else {\n        throw new IllegalArgumentException(\n            \"Motion path theme attribute must either be an enum value or path data string\");\n      }\n    }\n    return null;\n  }\n\n  static ShapeAppearanceModel convertToRelativeCornerSizes(\n      ShapeAppearanceModel shapeAppearanceModel, final RectF bounds) {\n    return shapeAppearanceModel.withTransformedCornerSizes(\n        cornerSize -> RelativeCornerSize.createFromCornerSize(bounds, cornerSize));\n  }\n\n  // TODO: rethink how to interpolate more than just corner size\n  static ShapeAppearanceModel transformCornerSizes(\n      ShapeAppearanceModel shapeAppearanceModel1,\n      ShapeAppearanceModel shapeAppearanceModel2,\n      RectF shapeAppearanceModel1Bounds,\n      CornerSizeBinaryOperator op) {","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/material-components/material-components-android/blob/ac7e18efeefb331850c561faf9ab8bf81d27ba68/lib/java/com/google/android/material/transition/platform/TransitionUtils.java#L101-L137","documentation":"While resolving the motionPath theme attribute, TransitionUtils accepts exactly two TypedValue types: TYPE_INT_DEC (enum 0=linear, 1=arc) and TYPE_STRING (path data parsed by PathParser into a PatternPathMotion). If the attribute resolves to any other type — a float/dimension (TYPE_DIMENSION, TYPE_FLOAT), a color, a boolean, or a reference to a non-string resource — the else branch throws IllegalArgumentException('Motion path theme attribute must either be an enum value or path data string'). The message names the required contract.","triggerScenarios":"Setting the motionPath theme item to a dimen (@dimen/motion_path), a boolean, a reference to another resource (<item name=\"motionPath\">@string/curve</item> is a string so OK, but @integer/... via reference, or a raw float like 0.5), or a color value; tools generating theme values with the wrong aapt type.","commonSituations":"Design tokens pipelines writing a numeric token into the attribute; copy-paste between attrs with different formats (e.g., putting a dimen where an enum/path belongs); theme overlays from a library that declare the attr with an incompatible format.","solutions":["Change the theme item to a plain integer (0 or 1) or a path-data string literal, matching the attribute's declared format (enum|string).","If the value lives in another resource, inline it as a string literal — references that resolve to non-int/non-string types are rejected.","Run aapt2 dump or lint on the final merged resources to find which merged theme supplies the bad-typed value.","If you control the attr declaration, keep its format=\"enum|string\" so aapt rejects invalid types at build time."],"exampleFix":"<!-- before -->\n<item name=\"motionPath\">@dimen/arc_amount</item>\n\n<!-- after -->\n<item name=\"motionPath\">1</item> <!-- arc -->","handlingStrategy":"validation","validationCode":"TypedValue v = new TypedValue();\nif (context.getTheme().resolveAttribute(R.attr.motionPath, v, true)) {\n  if (v.type != TypedValue.TYPE_INT_DEC && v.type != TypedValue.TYPE_STRING) {\n    throw new IllegalStateException(\n        \"motionPath must be an enum int (0/1) or a path data string, was type \" + v.type);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  applyThemePathMotion(context, transition, R.attr.motionPath);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"must either be an enum value\")) {\n    transition.setPathMotion(new MaterialArcMotion()); // sensible default instead of crash\n  } else {\n    throw e;\n  }\n}","preventionTips":["Never point the motionPath item at dimens, booleans, colors, or arbitrary references.","If tokens drive themes from a design pipeline, type-check them in CI before merging resources.","Prefer string path data for custom curves; it is unambiguous and human-readable."],"tags":["android","material-components","transition","theme","typed-value"],"backgroundTag":null,"analyzedSha":"ac7e18efeefb331850c561faf9ab8bf81d27ba68","analyzedAt":"2026-08-14T15:35:35.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}