JakeWharton/butterknife · error · IllegalStateException

Bindings already cleared.

Error message

Bindings already cleared.

What it means

Thrown by CompositeUnbinder.unbind() when unbind() is called more than once on the same binding. The composite nulls out its list of unbinders after the first unbind() and treats a second call as a programmer error (double-unbind), because views would be re-released after the target is already detached.

Source

Thrown at butterknife-reflect/src/main/java/butterknife/CompositeUnbinder.java:16

package butterknife;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.List;

final class CompositeUnbinder implements Unbinder {
  private @Nullable List<Unbinder> unbinders;

  CompositeUnbinder(@NonNull List<Unbinder> unbinders) {
    this.unbinders = unbinders;
  }

  @Override public void unbind() {
    if (unbinders == null) {
      throw new IllegalStateException("Bindings already cleared.");
    }
    for (Unbinder unbinder : unbinders) {
      unbinder.unbind();
    }
    unbinders = null;
  }
}

View on GitHub (pinned to fcdebedf32)

Solutions

  1. Guard the call: keep the Unbinder in a field, null it after unbind(), and check for null before calling (`if (unbinder != null) { unbinder.unbind(); unbinder = null; }`).
  2. Unbind in exactly one lifecycle method — onDestroyView for fragments that bind in onCreateView.
  3. Remove duplicate unbind() calls in base classes, subclasses, and manual cleanup paths.

Example fix

// before
@Override public void onDestroyView() { unbinder.unbind(); }
@Override public void onDestroy() { unbinder.unbind(); } // throws second time

// after
@Override public void onDestroyView() {
  if (unbinder != null) { unbinder.unbind(); unbinder = null; }
}
Defensive patterns

Strategy: validation

Validate before calling

if (unbinder != null) {
  unbinder.unbind();
  unbinder = null; // guard set immediately after use
}

Prevention

When it happens

Trigger: Calling ButterKnife.unbind(target) (or the generated/reflect Unbinder's unbind()) twice on the same target — e.g. unbind() in both onDestroyView() and onDestroy(), or onDestroy() plus a manual cleanup path, or unbinding a field that a lifecycle callback also unbinds.

Common situations: Fragments with defensive cleanup in multiple lifecycle methods; base fragment classes that call unbind() while a subclass also does; rebinding-then-unbinding flows where the old Unbinder reference is kept and unbound again during onDestroy. Modern ButterKnife (8.x+) switched to requiring each Unbider to be unbound exactly once and made double-unbind this explicit IllegalStateException.

Related errors


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