{"record":{"id":"b81002bd02020cd3","repo":"material-components/material-components-android","slug":"resourcename-is-not-a-valid-ancestor","errorCode":null,"errorMessage":"> resourceName < is not a valid ancestor","messagePattern":"> resourceName < is not a valid ancestor","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"lib/java/com/google/android/material/transition/TransitionUtils.java","lineNumber":285,"sourceCode":"      return descendant;\n    }\n    return findAncestorById(view, viewId);\n  }\n\n  static View findAncestorById(View view, @IdRes int ancestorId) {\n    String resourceName = view.getResources().getResourceName(ancestorId);\n    while (view != null) {\n      if (view.getId() == ancestorId) {\n        return view;\n      }\n      ViewParent parent = view.getParent();\n      if (parent instanceof View) {\n        view = (View) parent;\n      } else {\n        break;\n      }\n    }\n    throw new IllegalArgumentException(resourceName + \" is not a valid ancestor\");\n  }\n\n  static RectF getRelativeBounds(View view) {\n    return new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());\n  }\n\n  static Rect getRelativeBoundsRect(View view) {\n    return new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());\n  }\n\n  static RectF getLocationInWindow(View view) {\n    int[] location = new int[2];\n    view.getLocationInWindow(location);\n    int left = location[0];\n    int top = location[1];\n    int right = left + view.getWidth();\n    int bottom = top + view.getHeight();\n    return new RectF(left, top, right, bottom);","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/material-components/material-components-android/blob/ac7e18efeefb331850c561faf9ab8bf81d27ba68/lib/java/com/google/android/material/transition/TransitionUtils.java#L267-L303","documentation":"TransitionUtils.findAncestorById (around TransitionUtils.java:285) walks up the view hierarchy from a starting view looking for an ancestor with the given id; if the root is reached without a match, it throws IllegalArgumentException naming the resolved resource (\"<name> is not a valid ancestor\"). The id must belong to a parent/ancestor in the same inflated hierarchy — sibling ids, descendant ids, or ids from other fragments simply will not be found.","triggerScenarios":"Passing a targetViewResId to MaterialContainerTransform that is not actually an ancestor of the transitioned view; referencing a view id in a different fragment or a sibling container; calling findAncestorById before the view is attached to its full hierarchy (view detached or not yet added).","commonSituations":"Container transform configured with the wrong resource id (copy-paste of a target id); fragment view hierarchies where the \"ancestor\" lives in the activity layout but the start view is in a fragment that is not yet attached; RecyclerView item views whose assumed ancestor id exists only in some view holders.","solutions":["Verify the id passed as the ancestor belongs to a real parent/ancestor of the start view in the same inflated tree.","Run the lookup only after the view is attached (do it in onViewCreated/onAttachedToWindow, not in inflate-time callbacks).","If the target is in a different hierarchy, restructure so both views share one common ancestor before starting the transform."],"exampleFix":"// before\ntransform.setTargetViewId(R.id.wrong_container); // not an ancestor of startView\n\n// after\n// ensure R.id.real_container wraps startView in the same layout\ntransform.setTargetViewId(R.id.real_container);","handlingStrategy":"validation","validationCode":"static View findAncestorOrNull(View start, @IdRes int ancestorId) {\n  View v = start;\n  while (v != null) {\n    if (v.getId() == ancestorId) return v;\n    ViewParent p = v.getParent();\n    v = p instanceof View ? (View) p : null;\n  }\n  return null; // caller decides: skip transform or fail with its own message\n}\nView target = findAncestorOrNull(startView, R.id.target_container);\nif (target != null) transform.setTargetView(target); else Log.w(TAG, \"ancestor missing; skipping transform\");","typeGuard":"static boolean hasAncestorWithId(View v, @IdRes int id) {\n  for (ViewParent p = v.getParent(); p != null; p = p.getParent()) {\n    if (p instanceof View && ((View) p).getId() == id) return true;\n  }\n  return false;\n}","tryCatchPattern":null,"preventionTips":["Double-check targetViewId ids against the inflated hierarchy before starting the transform.","Start transforms after the view is attached (onViewCreated/onAttachedToWindow).","In lists/fragments, verify the ancestor exists for the specific view instance, not just in the layout file."],"tags":["android","material-components","view-hierarchy","ancestor-lookup","container-transform"],"backgroundTag":null,"analyzedSha":"ac7e18efeefb331850c561faf9ab8bf81d27ba68","analyzedAt":"2026-08-14T15:35:35.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}