{"record":{"id":"1e167cf5b52fb92c","repo":"JakeWharton/butterknife","slug":"bindings-already-cleared","errorCode":null,"errorMessage":"Bindings already cleared.","messagePattern":"Bindings already cleared\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"butterknife-reflect/src/main/java/butterknife/CompositeUnbinder.java","lineNumber":16,"sourceCode":"package butterknife;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport java.util.List;\n\nfinal class CompositeUnbinder implements Unbinder {\n  private @Nullable List<Unbinder> unbinders;\n\n  CompositeUnbinder(@NonNull List<Unbinder> unbinders) {\n    this.unbinders = unbinders;\n  }\n\n  @Override public void unbind() {\n    if (unbinders == null) {\n      throw new IllegalStateException(\"Bindings already cleared.\");\n    }\n    for (Unbinder unbinder : unbinders) {\n      unbinder.unbind();\n    }\n    unbinders = null;\n  }\n}\n","sourceCodeStart":1,"sourceCodeEnd":24,"githubUrl":"https://github.com/JakeWharton/butterknife/blob/fcdebedf3276096db2f51bf6372b849b5a9c75ed/butterknife-reflect/src/main/java/butterknife/CompositeUnbinder.java#L1-L24","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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; }`).","Unbind in exactly one lifecycle method — onDestroyView for fragments that bind in onCreateView.","Remove duplicate unbind() calls in base classes, subclasses, and manual cleanup paths."],"exampleFix":"// before\n@Override public void onDestroyView() { unbinder.unbind(); }\n@Override public void onDestroy() { unbinder.unbind(); } // throws second time\n\n// after\n@Override public void onDestroyView() {\n  if (unbinder != null) { unbinder.unbind(); unbinder = null; }\n}","handlingStrategy":"validation","validationCode":"if (unbinder != null) {\n  unbinder.unbind();\n  unbinder = null; // guard set immediately after use\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store the Unbinder in a field; null it immediately after unbind().","Unbind exactly once — onDestroyView for fragments, onDestroy for activities.","Audit base classes for duplicate unbind() calls."],"tags":["butterknife","lifecycle","double-free","unbind","fragment"],"backgroundTag":null,"analyzedSha":"fcdebedf3276096db2f51bf6372b849b5a9c75ed","analyzedAt":"2026-08-14T10:13:55.083Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}