google/guava · error · IllegalStateException

A compound CollectionSize doesn't specify a number of elemen

Error message

A compound CollectionSize doesn't specify a number of elements.

What it means

Thrown by CollectionSize.getNumElements() when called on a compound size. ZERO/ONE/SEVERAL each carry a concrete element count; the compound ANY (built from the other three) has numElements == null because it does not represent a single size. The generator iterates concrete sizes, so asking ANY for a count is a programmer error.

Source

Thrown at android/guava-testlib/src/com/google/common/collect/testing/features/CollectionSize.java:84

    this.implied = emptySet();
    this.numElements = numElements;
  }

  CollectionSize(Feature<? super Collection>... implied) {
    // Keep the order here, so that PerCollectionSizeTestSuiteBuilder
    // gives a predictable order of test suites.
    this.implied = copyToSet(implied);
    this.numElements = null;
  }

  @Override
  public Set<Feature<? super Collection>> getImpliedFeatures() {
    return implied;
  }

  public int getNumElements() {
    if (numElements == null) {
      throw new IllegalStateException(
          "A compound CollectionSize doesn't specify a number of elements.");
    }
    return numElements;
  }

  @Retention(RetentionPolicy.RUNTIME)
  @Inherited
  @TesterAnnotation
  public @interface Require {
    CollectionSize[] value() default {};

    CollectionSize[] absent() default {};
  }
}

View on GitHub (pinned to 94f39958ba)

Solutions

  1. Expand compound sizes before calling getNumElements(): iterate the concrete values CollectionSize.ZERO/ONE/SEVERAL, or filter the set to non-compound members.
  2. Guard calls with a check (e.g. size != CollectionSize.ANY) before invoking getNumElements().
  3. Use the builder's size-splitting path (PerCollectionSizeTestSuiteBuilder) which already expands ANY rather than calling getNumElements() on it.

Example fix

// before
int n = CollectionSize.ANY.getNumElements();

// after
for (CollectionSize size : asList(CollectionSize.ZERO, CollectionSize.ONE, CollectionSize.SEVERAL)) {
  int n = size.getNumElements();
  // ...
}
Defensive patterns

Strategy: validation

Validate before calling

for (CollectionSize s : sizes) {
  if (s == CollectionSize.ANY) continue; // skip compound
  int n = s.getNumElements();
}

Type guard

static boolean isConcreteSize(CollectionSize s) { return s != CollectionSize.ANY && s.getNumElementsIfExists() != null; }

Prevention

When it happens

Trigger: Calling CollectionSize.ANY.getNumElements(), or passing ANY into code (e.g. OneSizeGenerator) that calls getNumElements() directly instead of first expanding ANY into its implied concrete sizes.

Common situations: Writing a custom generator/tester that iterates over a feature set and calls getNumElements() without filtering out compound features; assuming ANY is a concrete size.

Related errors


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