JakeWharton/butterknife · error · IllegalStateException
@BindString field type must be 'String'. (
Error message
@BindString field type must be 'String'. (
What it means
Thrown by the reflection-based ButterKnife runtime when a field annotated with @BindString is not declared as java.lang.String. The binder calls context.getString(id) and only assigns to a String field; CharSequence, Spanned, or int fields fail the exact type check.
Source
Thrown at butterknife-reflect/src/main/java/butterknife/ButterKnife.java:653
return Unbinder.EMPTY;
}
private static @Nullable Unbinder parseBindString(Object target, Field field, View source) {
BindString bindString = field.getAnnotation(BindString.class);
if (bindString == null) {
return null;
}
validateMember(field);
int id = bindString.value();
Context context = source.getContext();
Class<?> fieldType = field.getType();
Object value;
if (fieldType == String.class) {
value = context.getString(id);
} else {
throw new IllegalStateException("@BindString field type must be 'String'. ("
+ field.getDeclaringClass().getName()
+ '.'
+ field.getName()
+ ')');
}
trySet(field, target, value);
return Unbinder.EMPTY;
}
private static @Nullable Unbinder parseOnCheckedChanged(final Object target, final Method method,
View source) {
OnCheckedChanged onCheckedChanged = method.getAnnotation(OnCheckedChanged.class);
if (onCheckedChanged == null) {
return null;
}
validateMember(method);
validateReturnType(method, void.class);View on GitHub (pinned to fcdebedf32)
Solutions
- Declare the field as `String`.
- If CharSequence/Spanned is needed, bind a String field and wrap it (e.g. Html.fromHtml) afterwards.
- Switch to butterknife-compiler so the mismatch is caught at compile time.
Example fix
// before @BindString(R.string.welcome) CharSequence welcome; // after @BindString(R.string.welcome) String welcome;
Defensive patterns
Strategy: type-guard
Validate before calling
for (Field f : targetClass.getDeclaredFields()) {
if (f.isAnnotationPresent(BindString.class) && f.getType() != String.class) {
throw new IllegalStateException(f + " must be String");
}
} Type guard
static boolean isValidBindStringField(Field f) {
return !f.isAnnotationPresent(BindString.class) || f.getType() == String.class;
} Prevention
- Declare @BindString fields as java.lang.String (not CharSequence).
- Convert to styled text after bind if needed.
- Prefer butterknife-compiler for build-time validation.
When it happens
Trigger: ButterKnife.bind(...) via butterknife-reflect on a class with `@BindString(R.string.label) CharSequence label;` or `@BindString(R.string.label) int labelResId;`.
Common situations: Declaring the field as CharSequence to accept styled/Spanned strings from other code paths, or annotating a resource-id field instead of the text field. The compiler path fails the build for this; reflect defers it to runtime (frequent in unit-test setups using butterknife-reflect).
Related errors
- @BindDimen field type must be 'int' or 'float'. (
- @BindDrawable field type must be 'Drawable'. (
- @BindFloat field type must be 'float'. (
- @BindFont field type must be 'Typeface'. (
- @BindInt field type must be 'int'. (
AI-assisted analysis of JakeWharton/butterknife@fcdebedf32 (2026-08-14).
Data as JSON: /api/errors/c28fea4e97085102.
Report an issue: GitHub.