google/guava · error · IllegalStateException

Call withFeatures() before createTestSuite().

Error message

Call withFeatures() before createTestSuite().

What it means

Thrown by checkCanCreate() when createTestSuite() is invoked without withFeatures(...). The feature set drives which testers are selected/filtered, so an empty feature set would produce an empty, meaningless suite; the builder rejects it up front.

Source

Thrown at android/guava-testlib/src/com/google/common/collect/testing/FeatureSpecificTestSuiteBuilder.java:215

      TestSuite testerSuite =
          makeSuiteForTesterClass((Class<? extends AbstractTester<?>>) testerClass);
      if (testerSuite.countTestCases() > 0) {
        suite.addTest(testerSuite);
      }
    }
    return suite;
  }

  /** Throw {@link IllegalStateException} if {@link #createTestSuite()} can't be called yet. */
  protected void checkCanCreate() {
    if (subjectGenerator == null) {
      throw new IllegalStateException("Call using() before createTestSuite().");
    }
    if (name == null) {
      throw new IllegalStateException("Call named() before createTestSuite().");
    }
    if (features == null) {
      throw new IllegalStateException("Call withFeatures() before createTestSuite().");
    }
  }

  @SuppressWarnings("rawtypes") // class literals
  protected abstract List<Class<? extends AbstractTester>> getTesters();

  private boolean matches(Test test) {
    Method method;
    try {
      method = extractMethod(test);
    } catch (IllegalArgumentException e) {
      logger.finer(Platform.format("%s: including by default: %s", test, e.getMessage()));
      return true;
    }
    if (suppressedTests.contains(method)) {
      logger.finer(Platform.format("%s: excluding because it was explicitly suppressed.", test));
      return false;
    }

View on GitHub (pinned to 94f39958ba)

Solutions

  1. Add .withFeatures(...) with the concrete features the implementation supports (e.g. CollectionFeature.GENERAL_PURPOSE, CollectionSize.ANY) before createTestSuite().
  2. Confirm the feature list is non-empty and that the constants are imported from the correct feature enum (CollectionFeature, MapFeature, ListFeature, SetFeature).
  3. Keep the canonical chain order using(...) -> named(...) -> withFeatures(...) -> createTestSuite().

Example fix

// before
TestSuite suite = ListTestSuiteBuilder.using(gen)
    .named("MyList")
    .createTestSuite();

// after
TestSuite suite = ListTestSuiteBuilder.using(gen)
    .named("MyList")
    .withFeatures(ListFeature.GENERAL_PURPOSE, CollectionSize.ANY)
    .createTestSuite();
Defensive patterns

Strategy: validation

Validate before calling

Feature<?>[] feats = { CollectionFeature.GENERAL_PURPOSE, CollectionSize.ANY };
if (feats.length == 0) throw new IllegalArgumentException("withFeatures() needs >=1 feature");
TestSuite suite = ListTestSuiteBuilder.using(gen).named("MyList").withFeatures(feats).createTestSuite();

Prevention

When it happens

Trigger: A builder chain missing the .withFeatures(...) step, or passing an empty varargs/iterable. features == null at line 214 (withFeatures sets it to a non-null set) trips the guard.

Common situations: Porting a suite and forgetting to copy the feature list; passing withFeatures() with no arguments; deleting features while debugging and forgetting to restore them.

Related errors


AI-assisted analysis of google/guava@94f39958ba (2026-08-13). Data as JSON: /api/errors/8de404746ca88003. Report an issue: GitHub.