JakeWharton/butterknife · error · IllegalStateException
@BindView fields must extend from View or be an interface. (
Error message
@BindView fields must extend from View or be an interface. (
What it means
parseBindView requires the annotated field's type to be a subclass of android.view.View or an interface (so the found view can be cast). Any other type — a String, a Drawable, a primitive, or a non-View class — throws this IllegalStateException during ButterKnife.bind in the reflect flavor. The compiler flavor enforces the same rule at build time; the reflect flavor enforces it at runtime.
Source
Thrown at butterknife-reflect/src/main/java/butterknife/ButterKnife.java:250
if (debug) Log.d(TAG, "MISS: Reached framework class. Abandoning search.");
return Unbinder.EMPTY;
}
if (debug) Log.d(TAG, "HIT: Reflectively found " + unbinders.size() + " bindings.");
return new CompositeUnbinder(unbinders);
}
private static @Nullable Unbinder parseBindView(Object target, Field field, View source) {
BindView bindView = field.getAnnotation(BindView.class);
if (bindView == null) {
return null;
}
validateMember(field);
int id = bindView.value();
Class<?> viewClass = field.getType();
if (!View.class.isAssignableFrom(viewClass) && !viewClass.isInterface()) {
throw new IllegalStateException(
"@BindView fields must extend from View or be an interface. ("
+ field.getDeclaringClass().getName()
+ '.'
+ field.getName()
+ ')');
}
String who = "field '" + field.getName() + "'";
Object view = Utils.findOptionalViewAsType(source, id, who, viewClass);
trySet(field, target, view);
return new FieldUnbinder(target, field);
}
private static @Nullable Unbinder parseBindViews(Object target, Field field, View source) {
BindViews bindViews = field.getAnnotation(BindViews.class);
if (bindViews == null) {
return null;View on GitHub (pinned to fcdebedf32)
Solutions
- Change the field type to a View subclass matching the XML tag (TextView, ImageView, custom View)
- If the ID refers to a resource rather than a view, use the matching annotation: @BindString, @BindDrawable, @BindColor, @BindDimen
- For collections of views use @BindViews with a List or array of a View type
Example fix
// before @BindView(R.id.user_name) String userName; // after @BindView(R.id.user_name) TextView userNameView;
Defensive patterns
Strategy: type-guard
Validate before calling
Class<?> t = field.getType();
if (!View.class.isAssignableFrom(t) && !t.isInterface()) {
throw new IllegalStateException("@BindView on non-View field: " + field);
} Type guard
static boolean isBindableViewType(Class<?> c) {
return View.class.isAssignableFrom(c) || c.isInterface();
} Prevention
- Use @BindView only for View subclasses or interfaces (e.g. CheckableView)
- Use @BindString/@BindDrawable/@BindColor for non-view resources
- Prefer the annotation processor over butterknife-reflect so type errors surface at compile time
When it happens
Trigger: Annotating a field of a non-View type with @BindView, e.g. `@BindView(R.id.name) String name;` or `@BindView(R.id.icon) Drawable icon;`; using a custom class that wraps a view instead of extending View.
Common situations: Migrating from findViewById-style code where an id mapped to a resource rather than a view; intending @BindString/@BindDrawable but typing @BindView; generics or Parcelable fields annotated by mistake.
Related errors
- @BindViews must be a List or array. (
- @BindViews List or array type must extend from View or be an
- @BindAnim field type must be 'Animation'. (
- @BindArray field type must be one of: String[], int[], CharS
- @BindBitmap field type must be 'Bitmap'. (
AI-assisted analysis of JakeWharton/butterknife@fcdebedf32 (2026-08-14).
Data as JSON: /api/errors/8acc5506993927dd.
Report an issue: GitHub.