JakeWharton/butterknife · error · IllegalStateException

Required view '{}' with ID {} for {} was not found. If this

Error message

Required view '{}' with ID {} for {} was not found. If this view is optional add '@Nullable' (fields) or '@Optional' (methods) annotation.

What it means

Thrown by Utils.findRequiredView (used by generated/reflect bindings for non-@Nullable @BindView fields and non-@Optional listener methods) when findViewById for the requested ID returns null on the bound source view hierarchy. The message includes the resource entry name, numeric ID, and the 'who' description (class.field), and tells you the escape hatches.

Source

Thrown at butterknife-runtime/src/main/java/butterknife/internal/Utils.java:84

  @SafeVarargs
  public static <T> List<T> listFilteringNull(T... views) {
    return new ImmutableList<>(arrayFilteringNull(views));
  }

  public static <T> T findOptionalViewAsType(View source, @IdRes int id, String who,
      Class<T> cls) {
    View view = source.findViewById(id);
    return castView(view, id, who, cls);
  }

  public static View findRequiredView(View source, @IdRes int id, String who) {
    View view = source.findViewById(id);
    if (view != null) {
      return view;
    }
    String name = getResourceEntryName(source, id);
    throw new IllegalStateException("Required view '"
        + name
        + "' with ID "
        + id
        + " for "
        + who
        + " was not found. If this view is optional add '@Nullable' (fields) or '@Optional'"
        + " (methods) annotation.");
  }

  public static <T> T findRequiredViewAsType(View source, @IdRes int id, String who,
      Class<T> cls) {
    View view = findRequiredView(source, id, who);
    return castView(view, id, who, cls);
  }

  public static <T> T castView(View view, @IdRes int id, String who, Class<T> cls) {
    try {
      return cls.cast(view);

View on GitHub (pinned to fcdebedf32)

Solutions

  1. Verify the inflated layout actually declares the ID; align flavor/orientation variants that omit it.
  2. Move ButterKnife.bind into onCreateView/onViewCreated (fragment) or after setContentView (activity).
  3. If the view is genuinely optional, annotate the field @Nullable (butterknife.@Nullable) or the method @Optional so a missing view is skipped.

Example fix

// before
@BindView(R.id.subtitle) TextView subtitle; // absent in landscape layout

// after
@Nullable @BindView(R.id.subtitle) TextView subtitle; // null-safe in landscape
Defensive patterns

Strategy: validation

Validate before calling

// Before bind: confirm the required view exists
View v = sourceView.findViewById(R.id.subtitle);
if (v == null && !fieldIsAnnotatedNullable) {
  // align layout, bind later, or mark @Nullable
}

Prevention

When it happens

Trigger: ButterKnife.bind(this) where @BindView(R.id.title) is required, but the content view inflated (setContentView / fragment layout) has no view with that ID — wrong layout inflated, ID only in a different flavor/build variant layout, child view not yet inflated, or binding on the wrong source (ButterKnife.bind(this, drawerHeader) etc.).

Common situations: Landscape/night/flavor layout variants missing a view present in the default layout; multi-pane vs single-pane layout swap; binding before the view exists (bind before setContentView, or in a fragment before onViewCreated); binding a header/footer row layout where the ID belongs to the row layout but bind was called on the item container. Library consumers commonly hit it after renaming or removing an ID in XML while annotations still reference it.

Related errors


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