JakeWharton/butterknife · error · IllegalStateException

@BindViews List or array type must extend from View or be an

Error message

@BindViews List or array type must extend from View or be an interface. (

What it means

After resolving the component type of a @BindViews List or array, the reflect binder requires that component to be a View subclass or an interface (the compiler enforces the same rule). If the element type is something like String, Integer, or a non-View POJO, bind throws this IllegalStateException.

Source

Thrown at butterknife-reflect/src/main/java/butterknife/ButterKnife.java:298

        Type viewType = ((ParameterizedType) fieldType).getActualTypeArguments()[0];
        // TODO real rawType impl!!!!
        viewClass = (Class<?>) viewType;
      } else {
        throw new IllegalStateException("@BindViews List must have a generic component. ("
            + field.getDeclaringClass().getName()
            + '.'
            + field.getName()
            + ')');
      }
    } else {
      throw new IllegalStateException("@BindViews must be a List or array. ("
          + field.getDeclaringClass().getName()
          + '.'
          + field.getName()
          + ')');
    }
    if (!View.class.isAssignableFrom(viewClass) && !viewClass.isInterface()) {
      throw new IllegalStateException(
          "@BindViews List or array type must extend from View or be an interface. ("
              + field.getDeclaringClass().getName()
              + '.'
              + field.getName()
              + ')');
    }

    int[] ids = bindViews.value();
    if (ids.length == 0) {
      throw new IllegalStateException("@BindViews must specify at least one ID. ("
          + field.getDeclaringClass().getName()
          + '.'
          + field.getName()
          + ')');
    }

    List<Object> views = new ArrayList<>(ids.length);
    String who = "field '" + field.getName() + "'";

View on GitHub (pinned to fcdebedf32)

Solutions

  1. Change the component type to a View subclass, e.g. List<TextView>
  2. For non-view resources use the single-value annotations (@BindString, @BindDrawable) on separate fields

Example fix

// before
@BindViews({R.id.first, R.id.second})
List<String> labels;

// after
@BindViews({R.id.first, R.id.second})
List<TextView> labels;
Defensive patterns

Strategy: type-guard

Validate before calling

Class<?> component = /* resolved component type */;
if (!View.class.isAssignableFrom(component) && !component.isInterface()) {
  throw new IllegalStateException("@BindViews component not a View: " + component);
}

Type guard

static boolean isBindableComponent(Class<?> c) {
  return View.class.isAssignableFrom(c) || c.isInterface();
}

Prevention

When it happens

Trigger: `@BindViews({R.id.a}) List<String> names;` or `@BindViews({...}) String[] names;` — component types that are not Views.

Common situations: Trying to batch-bind string/resource values with a view annotation; refactoring a List<TextView> into a list of model objects while leaving @BindViews on it.

Related errors


AI-assisted analysis of JakeWharton/butterknife@fcdebedf32 (2026-08-14). Data as JSON: /api/errors/207174401a51bb0a. Report an issue: GitHub.