{"record":{"id":"d64f1fdfbee254fb","repo":"material-components/material-components-android","slug":"didn-t-find-listitemlayout-in-root-itemview-or-amo","errorCode":null,"errorMessage":"Didn't find ListItemLayout in root itemView or among itemView's children.","messagePattern":"Didn't find ListItemLayout in root itemView or among itemView's children\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"lib/java/com/google/android/material/listitem/ListItemViewHolder.java","lineNumber":51,"sourceCode":"  public ListItemViewHolder(@NonNull View itemView) {\n    super(itemView);\n    listItemLayout = findListItemLayout();\n  }\n\n  @NonNull\n  private ListItemLayout findListItemLayout() {\n    if (itemView instanceof ListItemLayout) {\n      return (ListItemLayout) itemView;\n    } else if (itemView instanceof ViewGroup) {\n      int childCount = ((ViewGroup) itemView).getChildCount();\n      for (int i = 0; i < childCount; i++) {\n        View child = ((ViewGroup) itemView).getChildAt(i);\n        if (child instanceof ListItemLayout) {\n          return (ListItemLayout) child;\n        }\n      }\n    }\n    throw new IllegalStateException(\n        \"Didn't find ListItemLayout in root itemView or among itemView's children.\");\n  }\n\n  /**\n   * Binds the corresponding {@link ListItemLayout} to the adapter position by calling {@link\n   * ListItemLayout#updateAppearance}.\n   */\n  public void bind() {\n    int position = getBindingAdapterPosition();\n    int itemCount = getBindingAdapter().getItemCount();\n    bind(position, itemCount);\n  }\n\n  /**\n   * Binds the corresponding {@link ListItemLayout} according given position and item count.\n   * If there are several sections in the list, the position and item count given should be relative\n   * to its section.\n   */","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/material-components/material-components-android/blob/ac7e18efeefb331850c561faf9ab8bf81d27ba68/lib/java/com/google/android/material/listitem/ListItemViewHolder.java#L33-L69","documentation":"ListItemViewHolder's constructor locates the ListItemLayout it operates on: it checks whether the itemView itself is a ListItemLayout, otherwise scans the itemView's direct children for one. If none is found, the holder cannot bind swipe/appearance logic, so it throws IllegalStateException — this is a structural contract violation between your item layout and the holder.","triggerScenarios":"Creating a ListItemViewHolder with an item layout whose root is not ListItemLayout and which has no ListItemLayout as a DIRECT child (e.g. ListItemLayout nested two levels deep inside other containers); inflating the wrong layout resource for the holder.","commonSituations":"Wrapping the list item in an extra FrameLayout/CardView for decoration, pushing ListItemLayout below the first child level; layout refactors that rename or replace the ListItemLayout root; using a plain ViewHolder path with a generic item layout.","solutions":["Make ListItemLayout the root of the item layout, or ensure it is a direct child of the itemView root (depth exactly one).","Verify the adapter inflates the correct layout containing ListItemLayout when constructing ListItemViewHolder.","If you need extra decoration containers, put them INSIDE the ListItemLayout, not around it."],"exampleFix":"<!-- before: ListItemLayout nested too deep -->\n<FrameLayout ...>\n  <CardView ...>\n    <ListItemLayout .../> <!-- depth 2: holder throws -->\n  </CardView>\n</FrameLayout>\n\n<!-- after -->\n<ListItemLayout ...>\n  <CardView ...> ... content ... </CardView>\n</ListItemLayout>","handlingStrategy":"validation","validationCode":"View v = itemView instanceof ListItemLayout ? itemView\n    : (((ViewGroup) itemView).getChildCount() > 0 ? ((ViewGroup) itemView).getChildAt(0) : null);\nif (!(v instanceof ListItemLayout)) {\n  throw new IllegalStateException(\"Item layout must have ListItemLayout as root or direct child\");\n}","typeGuard":"static boolean hasDirectListItemLayout(View itemView) {\n  if (itemView instanceof ListItemLayout) return true;\n  if (itemView instanceof ViewGroup) {\n    ViewGroup g = (ViewGroup) itemView;\n    for (int i = 0; i < g.getChildCount(); i++) {\n      if (g.getChildAt(i) instanceof ListItemLayout) return true;\n    }\n  }\n  return false;\n}","tryCatchPattern":null,"preventionTips":["Make ListItemLayout the item layout root; wrap decorations inside it, not around it.","Add a lint/test asserting the inflated item layout's root tag is ListItemLayout.","Keep adapters and their layout resources paired via constants to avoid inflating the wrong layout."],"tags":["material-components","listitem","viewholder","layout-structure"],"backgroundTag":null,"analyzedSha":"ac7e18efeefb331850c561faf9ab8bf81d27ba68","analyzedAt":"2026-08-14T15:35:35.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}