apache/beam · error · IllegalArgumentException

Class is not exposed.

Error message

Class  is not exposed.

What it means

The private getAnyExposurePath(class, excluded) overload assumes the queried class has at least one 'exposer' (a class it is exposed through). If the exposure map has no entry, the class was never actually exposed, and the method throws IllegalArgumentException('Class X is not exposed.'). It is a precondition check protecting the graph walk from querying unindexed classes.

Solutions

  1. Check membership in the exposed set before requesting an exposure path for a class.
  2. Rebuild the ApiSurface with roots/predicates that include the queried class (see ApiSurface.of(rootClasses, predicates)).
  3. Treat this exception as 'not exposed' in tooling and report accordingly instead of crashing.

Example fix

// before
List<Class<?>> path = apiSurface.getAnyExposurePath(candidate);
// after
Set<Class<?>> exposed = apiSurface.getExposedClasses();
if (!exposed.contains(candidate)) { return; } // not exposed, skip
List<Class<?>> path = apiSurface.getAnyExposurePath(candidate);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!surface.getExposedClasses().contains(candidate)) { return; }

Try / catch

try {
  return surface.getAnyExposurePath(candidate);
} catch (IllegalArgumentException e) {
  return null; // not exposed
}

Prevention

When it happens

Trigger: The private path walk is entered with a class absent from getExposedToExposers() — practically reached when the public entry point (or recursive walk) is invoked for a class never registered as exposed on this ApiSurface instance.

Common situations: Querying an ApiSurface built for a different root set than the class of interest; classes filtered out by predicates (e.g. only-public-classes filters) but still passed to path lookups in custom tooling.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/4fa375a56747b6a7. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/util/ApiSurface.java:430

      return path;
    }
  }

  /**
   * Returns a path from an exposed class to a root class. There may be many, but this gives only
   * one. It will not return a path that crosses the excluded classes.
   *
   * <p>If there are only cycles or paths through the excluded classes, returns null.
   *
   * <p>If the class is not actually in the exposure map, throws IllegalArgumentException
   */
  private List<Class<?>> getAnyExposurePath(Class<?> exposedClass, Set<Class<?>> excluded) {
    List<Class<?>> exposurePath = Lists.newArrayList();
    exposurePath.add(exposedClass);

    Collection<Class<?>> exposers = getExposedToExposers().get(exposedClass);
    if (exposers.isEmpty()) {
      throw new IllegalArgumentException("Class " + exposedClass + " is not exposed.");
    }

    for (Class<?> exposer : exposers) {
      if (excluded.contains(exposer)) {
        continue;
      }

      // A null exposer means this is already a root class.
      if (exposer == null) {
        return exposurePath;
      }

      List<Class<?>> restOfPath =
          getAnyExposurePath(exposer, Sets.union(excluded, Sets.newHashSet(exposer)));

      if (restOfPath != null) {
        exposurePath.addAll(restOfPath);
        return exposurePath;

View on GitHub (pinned to 12126d8942)