airbnb/epoxy · error · IllegalArgumentException

0 is an invalid value for required strings.

Error message

0 is an invalid value for required strings.

What it means

StringAttributeData validates that string resources passed to an Epoxy model attribute are non-zero. `0` is the Android framework's sentinel for 'no resource' and `Resources.getString(0)` would fail; Epoxy rejects it eagerly with `IllegalArgumentException` instead of letting a confusing NotFound crash happen later. Required string attributes must always receive a valid, non-zero resource ID or a literal string.

Solutions

  1. Pass a real, non-zero `@StringRes` resource ID (e.g. `R.string.title`) to the attribute.
  2. If the value may be absent, make the attribute optional with `.title(null)` via a nullable/text setter instead of passing 0.
  3. Set a literal string with `.title("Some text")` when you don't have a resource.
  4. Check upstream defaults: initialize resource-ID fields to `R.string.empty` or `View.NO_ID` and guard before calling the setter.
  5. Verify the failing resource actually exists in the right module so it isn't resolving to 0.

Example fix

// before
int titleRes = 0; // never assigned
model.title(titleRes); // throws

// after
if (titleRes != 0) {
  model.title(titleRes);
} else {
  model.title(R.string.default_title);
}
Defensive patterns

Strategy: validation

Validate before calling

// Guard before calling a required string attribute
if (titleResId != 0) {
  model.title(titleResId);
} else {
  model.title(R.string.default_title); // or model.title(null) if optional
}

Prevention

When it happens

Trigger: Calling `setValue(0)` on a required string attribute — e.g. `.title(0)` or `.text(someResId)` where `someResId` defaulted to 0. Also happens when a generated model setter receives an uninitialized `@StringRes` field, or when `defaultStringRes` was left at 0 and the fallback path runs `setValue(0)`.

Common situations: A developer stores a resource ID in a field initialized to 0 and forgets to assign it; a server response lacks a value and the code passes 0 as a placeholder; a configurable attr is read from a config/bundle where the key is missing so `getInt` returns 0.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of airbnb/epoxy@e45bd3a61f (2026-09-13). Data as JSON: /api/errors/33fe475499aec97e. Report an issue: GitHub.

Appendix: source

Thrown at epoxy-adapter/src/main/java/com/airbnb/epoxy/StringAttributeData.java:71

    if (stringRes != 0) {
      this.stringRes = stringRes;
      this.formatArgs = formatArgs;
      string = null;
      pluralRes = 0;
    } else {
      handleInvalidStringRes();
    }
  }

  private void handleInvalidStringRes() {
    if (hasDefault) {
      if (defaultStringRes != 0) {
        setValue(defaultStringRes);
      } else {
        setValue(defaultString);
      }
    } else {
      throw new IllegalArgumentException("0 is an invalid value for required strings.");
    }
  }

  public void setValue(@PluralsRes int pluralRes, int quantity, @Nullable Object[] formatArgs) {
    if (pluralRes != 0) {
      this.pluralRes = pluralRes;
      this.quantity = quantity;
      this.formatArgs = formatArgs;
      string = null;
      stringRes = 0;
    } else {
      handleInvalidStringRes();
    }
  }

  public CharSequence toString(Context context) {
    if (pluralRes != 0) {
      if (formatArgs != null) {

View on GitHub (pinned to e45bd3a61f)