material-components/material-components-android · error · IllegalArgumentException
We already have an EditText, can only have one
Error message
We already have an EditText, can only have one
What it means
TextInputLayout is a container that wraps exactly one EditText. When a second EditText is added — either via XML (two EditText tags inside TextInputLayout) or programmatically through addView/setEditText — the private setEditText(TextInputLayout.java:1510) throws IllegalArgumentException because the internal this.editText field is already set. The library uses this single-editText invariant everywhere (hint, counter, error label all bind to that one field).
Source
Thrown at lib/java/com/google/android/material/textfield/TextInputLayout.java:1510
onProvideAutofillStructure(structure, flags);
onProvideAutofillVirtualStructure(structure, flags);
structure.setChildCount(inputFrame.getChildCount());
for (int i = 0; i < inputFrame.getChildCount(); i++) {
View child = inputFrame.getChildAt(i);
ViewStructure childStructure = structure.newChild(i);
child.dispatchProvideAutofillStructure(childStructure, flags);
if (child == editText) {
childStructure.setHint(getHint());
}
}
}
}
private void setEditText(EditText editText) {
// If we already have an EditText, throw an exception
if (this.editText != null) {
throw new IllegalArgumentException("We already have an EditText, can only have one");
}
if (getEndIconMode() != END_ICON_DROPDOWN_MENU && !(editText instanceof TextInputEditText)) {
Log.i(
LOG_TAG,
"EditText added is not a TextInputEditText. Please switch to using that"
+ " class instead.");
}
this.editText = editText;
if (minEms != NO_WIDTH) {
setMinEms(minEms);
} else {
setMinWidth(minWidth);
}
if (maxEms != NO_WIDTH) {
setMaxEms(maxEms);
} else {View on GitHub (pinned to ac7e18efee)
Solutions
- Ensure the TextInputLayout has exactly one EditText/TextInputEditText as a direct child in XML.
- If swapping fields at runtime, keep one EditText and change its inputType/text instead of adding another.
- If you truly need two inputs, use two separate TextInputLayout wrappers.
- If adding programmatically, remove the previous EditText from the TextInputLayout before adding the new one.
Example fix
<!-- before -->
<com.google.android.material.textfield.TextInputLayout ...>
<com.google.android.material.textfield.TextInputEditText ... />
<EditText ... /> <!-- second child: crashes -->
</com.google.android.material.textfield.TextInputLayout>
<!-- after -->
<com.google.android.material.textfield.TextInputLayout ...>
<com.google.android.material.textfield.TextInputEditText ... />
</com.google.android.material.textfield.TextInputLayout>
<!-- and a second TextInputLayout for the other field --> Defensive patterns
Strategy: validation
Validate before calling
boolean hasExactlyOneEditText(TextInputLayout til) {
int editTextCount = 0;
for (int i = 0; i < til.getChildCount(); i++) {
if (til.getChildAt(i) instanceof EditText) editTextCount++;
}
return editTextCount == 1;
}
// call before programmatically adding another EditText:
if (hasExactlyOneEditText(til)) throw new IllegalStateException("TextInputLayout already has an EditText"); Prevention
- Keep exactly one EditText per TextInputLayout in XML; review layouts after copy-paste edits.
- To swap inputs at runtime, mutate inputType/hint on the existing EditText rather than adding a new one.
- Treat lint/layout-inspection warnings about unexpected children in TextInputLayout as build errors.
When it happens
Trigger: Declaring two EditText (or TextInputEditText) elements as direct children of one TextInputLayout in a layout XML; calling textInputLayout.addView(editText) a second time; inflating a layout where programmatic code adds an EditText to a TextInputLayout that already absorbed one from XML.
Common situations: Copy-pasting a layout block and forgetting to remove the old EditText; dynamically swapping input fields (e.g. switching email -> username) by adding a new EditText instead of reconfiguring the existing one; merging layouts with <include> that each contain an EditText inside the same TextInputLayout.
Related errors
- MaterialSplitButton can only hold MaterialButtons.
- MaterialSplitButton can only hold two MaterialButtons.
- The view is not a child of CoordinatorLayout
- > resourceName < is not a valid ancestor
- > resourceName < is not a valid ancestor
AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14).
Data as JSON: /api/errors/53fe1d3f0ada2ee4.
Report an issue: GitHub.