JakeWharton/butterknife · error · IllegalStateException
@BindAnim field type must be 'Animation'. (
Error message
@BindAnim field type must be 'Animation'. (
What it means
@BindAnim loads an android.view.animation.Animation via AnimationUtils.loadAnimation and therefore only accepts a field whose exact type is Animation. parseBindAnim checks field.getType() == Animation.class; any other type — including a subclass like ScaleAnimation — throws this IllegalStateException at bind time.
Source
Thrown at butterknife-reflect/src/main/java/butterknife/ButterKnife.java:351
return new FieldUnbinder(target, field);
}
private static @Nullable Unbinder parseBindAnim(Object target, Field field, View source) {
BindAnim bindAnim = field.getAnnotation(BindAnim.class);
if (bindAnim == null) {
return null;
}
validateMember(field);
int id = bindAnim.value();
Context context = source.getContext();
Object value;
Class<?> fieldType = field.getType();
if (fieldType == Animation.class) {
value = AnimationUtils.loadAnimation(context, id);
} else {
throw new IllegalStateException("@BindAnim field type must be 'Animation'. ("
+ field.getDeclaringClass().getName()
+ '.'
+ field.getName()
+ ')');
}
trySet(field, target, value);
return Unbinder.EMPTY;
}
private static @Nullable Unbinder parseBindArray(Object target, Field field, View source) {
BindArray bindArray = field.getAnnotation(BindArray.class);
if (bindArray == null) {
return null;
}
validateMember(field);
int id = bindArray.value();View on GitHub (pinned to fcdebedf32)
Solutions
- Declare the field exactly as `Animation`: `@BindAnim(R.anim.fade) Animation fade;`
- For property animators, load them manually with AnimatorInflater/AnimatorInflaterCompat instead of @BindAnim
Example fix
// before @BindAnim(R.anim.fade_in) ScaleAnimation fadeIn; // after @BindAnim(R.anim.fade_in) Animation fadeIn;
Defensive patterns
Strategy: type-guard
Validate before calling
if (field.getType() != Animation.class) {
throw new IllegalStateException("@BindAnim field must be Animation: " + field);
} Type guard
static boolean isAnimationField(Field f) {
return f.getType() == android.view.animation.Animation.class;
} Prevention
- Type @BindAnim fields exactly as android.view.animation.Animation
- Use AnimatorInflater manually for property animators — @BindAnim does not support them
When it happens
Trigger: `@BindAnim(R.anim.fade) ScaleAnimation fade;` (subclass instead of Animation); typing the field as Object or a KTX animator type; intending an Animator/AnimatorSet (which is not supported by @BindAnim).
Common situations: Confusing view animations (Animation) with property animators (Animator) from android.animation; refactoring a field to the concrete animation class returned by a loader.
Related errors
- @BindView fields must extend from View or be an interface. (
- @BindViews must be a List or array. (
- @BindViews List or array type must extend from View or be an
- @BindArray field type must be one of: String[], int[], CharS
- @BindBitmap field type must be 'Bitmap'. (
AI-assisted analysis of JakeWharton/butterknife@fcdebedf32 (2026-08-14).
Data as JSON: /api/errors/de0dcfdc2284d9ab.
Report an issue: GitHub.