material-components/material-components-android · error · IllegalArgumentException
> resourceName < is not a valid ancestor
Error message
> resourceName < is not a valid ancestor
What it means
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.
Source
Thrown at lib/java/com/google/android/material/transition/TransitionUtils.java:285
return descendant;
}
return findAncestorById(view, viewId);
}
static View findAncestorById(View view, @IdRes int ancestorId) {
String resourceName = view.getResources().getResourceName(ancestorId);
while (view != null) {
if (view.getId() == ancestorId) {
return view;
}
ViewParent parent = view.getParent();
if (parent instanceof View) {
view = (View) parent;
} else {
break;
}
}
throw new IllegalArgumentException(resourceName + " is not a valid ancestor");
}
static RectF getRelativeBounds(View view) {
return new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
}
static Rect getRelativeBoundsRect(View view) {
return new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
}
static RectF getLocationInWindow(View view) {
int[] location = new int[2];
view.getLocationInWindow(location);
int left = location[0];
int top = location[1];
int right = left + view.getWidth();
int bottom = top + view.getHeight();
return new RectF(left, top, right, bottom);View on GitHub (pinned to ac7e18efee)
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.
Example fix
// before transform.setTargetViewId(R.id.wrong_container); // not an ancestor of startView // after // ensure R.id.real_container wraps startView in the same layout transform.setTargetViewId(R.id.real_container);
Defensive patterns
Strategy: validation
Validate before calling
static View findAncestorOrNull(View start, @IdRes int ancestorId) {
View v = start;
while (v != null) {
if (v.getId() == ancestorId) return v;
ViewParent p = v.getParent();
v = p instanceof View ? (View) p : null;
}
return null; // caller decides: skip transform or fail with its own message
}
View target = findAncestorOrNull(startView, R.id.target_container);
if (target != null) transform.setTargetView(target); else Log.w(TAG, "ancestor missing; skipping transform"); Type guard
static boolean hasAncestorWithId(View v, @IdRes int id) {
for (ViewParent p = v.getParent(); p != null; p = p.getParent()) {
if (p instanceof View && ((View) p).getId() == id) return true;
}
return false;
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- > resourceName < is not a valid ancestor
- MaterialSplitButton can only hold MaterialButtons.
- MaterialSplitButton can only hold two MaterialButtons.
- We already have an EditText, can only have one
- The view is not a child of CoordinatorLayout
AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14).
Data as JSON: /api/errors/b81002bd02020cd3.
Report an issue: GitHub.