JakeWharton/butterknife · error · IllegalStateException

@BindFont field type must be 'Typeface'. (

Error message

@BindFont field type must be 'Typeface'. (

What it means

Thrown by the reflection-based ButterKnife runtime when a field annotated with @BindFont is not declared as android.graphics.Typeface. The binder can only produce a Typeface from the font resource; any other declared type (String, int, a custom font wrapper) fails the exact field.getType() == Typeface.class check.

Source

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

      switch (style) {
        case Typeface.NORMAL:
          value = font;
          break;
        case Typeface.BOLD:
        case Typeface.ITALIC:
        case Typeface.BOLD_ITALIC:
          value = Typeface.create(font, style);
          break;
        default:
          throw new IllegalStateException(
              "@BindFont style must be NORMAL, BOLD, ITALIC, or BOLD_ITALIC. ("
                  + field.getDeclaringClass().getName()
                  + '.'
                  + field.getName()
                  + ')');
      }
    } else {
      throw new IllegalStateException("@BindFont field type must be 'Typeface'. ("
          + field.getDeclaringClass().getName()
          + '.'
          + field.getName()
          + ')');
    }
    trySet(field, target, value);

    return Unbinder.EMPTY;
  }

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

    int id = bindInt.value();

View on GitHub (pinned to fcdebedf32)

Solutions

  1. Declare the field as `Typeface` and apply it with view.setTypeface(...) afterwards.
  2. If a custom wrapper is needed, bind the Typeface field and construct the wrapper after bind.
  3. Move to butterknife-compiler for compile-time checking.

Example fix

// before
@BindFont(R.font.titles) String titleFont;

// after
@BindFont(R.font.titles) Typeface titleFont;
// then: textView.setTypeface(titleFont);
Defensive patterns

Strategy: type-guard

Validate before calling

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

Type guard

static boolean isValidBindFontField(Field f) {
  return !f.isAnnotationPresent(BindFont.class)
      || f.getType() == Typeface.class;
}

Prevention

When it happens

Trigger: ButterKnife.bind(...) via butterknife-reflect on a class with `@BindFont(R.font.montserrat) String fontName;` or `@BindFont(R.font.montserrat) int fontResId;` — any field whose type is not exactly Typeface.

Common situations: Annotating a resource-id int field or a custom font-wrapper field instead of the Typeface field that is actually applied to views; mixing up @BindFont with a font-name String convention used elsewhere in the project. The compiler path reports this at compile time; reflect defers it to runtime.

Related errors


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