JakeWharton/butterknife · error · IllegalStateException

@BindFloat field type must be 'float'. (

Error message

@BindFloat field type must be 'float'. (

What it means

Thrown by the reflection-based ButterKnife runtime when a field annotated with @BindFloat is not declared as primitive float. The binder reads the resource with Utils.getFloat and can only assign a float; doubles, boxed Floats, and ints are all rejected by the exact field.getType() == float.class check.

Source

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

    return Unbinder.EMPTY;
  }

  private static @Nullable Unbinder parseBindFloat(Object target, Field field, View source) {
    BindFloat bindInt = field.getAnnotation(BindFloat.class);
    if (bindInt == null) {
      return null;
    }
    validateMember(field);

    int id = bindInt.value();
    Context context = source.getContext();

    Class<?> fieldType = field.getType();
    Object value;
    if (fieldType == float.class) {
      value = Utils.getFloat(context, id);
    } else {
      throw new IllegalStateException("@BindFloat field type must be 'float'. ("
          + field.getDeclaringClass().getName()
          + '.'
          + field.getName()
          + ')');
    }
    trySet(field, target, value);

    return Unbinder.EMPTY;
  }

  private static @Nullable Unbinder parseBindFont(Object target, Field field, View source) {
    BindFont bindFont = field.getAnnotation(BindFont.class);
    if (bindFont == null) {
      return null;
    }
    validateMember(field);

    int id = bindFont.value();

View on GitHub (pinned to fcdebedf32)

Solutions

  1. Change the field to primitive `float`.
  2. If double precision is required afterwards, keep the float field and copy into a double after bind.
  3. Use @BindInt for integer resources or switch to butterknife-compiler for compile-time validation.

Example fix

// before
@BindFloat(R.dimen.aspect) Double aspect;

// after
@BindFloat(R.dimen.aspect) float aspect;
Defensive patterns

Strategy: type-guard

Validate before calling

for (Field f : targetClass.getDeclaredFields()) {
  if (f.isAnnotationPresent(BindFloat.class) && f.getType() != float.class) {
    throw new IllegalStateException(f + " must be float");
  }
}

Type guard

static boolean isValidBindFloatField(Field f) {
  return !f.isAnnotationPresent(BindFloat.class) || f.getType() == float.class;
}

Prevention

When it happens

Trigger: ButterKnife.bind(...) via butterknife-reflect on a class containing `@BindFloat(R.dimen.ratio) double ratio;`, `@BindFloat(R.dimen.ratio) Float ratio;`, or `@BindFloat(R.dimen.ratio) int ratio;`.

Common situations: Using double for precision math and expecting implicit widening, boxing the value for an ORM/JSON model, or annotating a resource that was assumed to be an integer. The annotation processor catches this at compile time; the reflect artifact (common in unit tests) defers it to runtime.

Related errors


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