JakeWharton/butterknife · error · IllegalStateException

@BindViews List must have a generic component. (

Error message

@BindViews List must have a generic component. (

What it means

parseBindViews accepts a List field only if its generic type is a parameterized type, so it can extract the component (element) view class from the type argument. A raw `List` (or a List whose generic info is erased/unavailable at reflection time) leaves no component class, so bind throws this IllegalStateException.

Source

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

    BindViews bindViews = field.getAnnotation(BindViews.class);
    if (bindViews == null) {
      return null;
    }
    validateMember(field);

    Class<?> fieldClass = field.getType();
    Class<?> viewClass;
    boolean isArray = fieldClass.isArray();
    if (isArray) {
      viewClass = fieldClass.getComponentType();
    } else if (fieldClass == List.class) {
      Type fieldType = field.getGenericType();
      if (fieldType instanceof ParameterizedType) {
        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()

View on GitHub (pinned to fcdebedf32)

Solutions

  1. Parameterize the field: `@BindViews({...}) List<TextView> textViews;`
  2. If you cannot use generics, switch to a typed array: `@BindViews({...}) TextView[] textViews;`

Example fix

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

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

Strategy: type-guard

Validate before calling

if (field.getType() == List.class
    && !(field.getGenericType() instanceof ParameterizedType)) {
  throw new IllegalStateException("Raw List for @BindViews: " + field);
}

Type guard

static boolean isParameterizedList(Field f) {
  return f.getType() == List.class
      && f.getGenericType() instanceof ParameterizedType;
}

Prevention

When it happens

Trigger: Declaring `@BindViews({R.id.a, R.id.b}) List views;` without a type argument; using a raw List type from a pre-generics codebase or an unchecked cast that erases the parameterization.

Common situations: Old Java 1.4-style code reused with ButterKnife; IDE warnings about raw types ignored; fields typed as List after refactoring away the generic parameter.

Related errors


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