apache/beam · error · IllegalArgumentException

Class has no path back to any root class. It should never…

Error message

Class  has no path back to any root class. It should never have been considered exposed.

What it means

ApiSurface tracks classes exposed from a set of root classes and records an exposure path from each exposed class back to a root. getAnyExposurePath(exposedClass) is an internal consistency check: if a class is in the exposed set but no path to any root exists, the index is corrupt, so it throws IllegalArgumentException. This is a library-internal invariant violation, not something caused by user data.

Solutions

  1. Only call getAnyExposurePath on classes returned by the surface's exposedClasses()/contains logic — verify membership first.
  2. Ensure the root classes supplied when building the ApiSurface actually cover the package of the class being queried.
  3. Wrap the call in try-catch for IllegalArgumentException if you are probing arbitrary classes, and fall back to reporting 'not exposed'.

Example fix

// before
List<Class<?>> path = apiSurface.getAnyExposurePath(SomeClass.class);
// after
if (apiSurface.getExposedClasses().contains(SomeClass.class)) {
  List<Class<?>> path = apiSurface.getAnyExposurePath(SomeClass.class);
} else {
  // class is not part of the tracked surface
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!surface.getExposedClasses().contains(clazz)) { /* skip */ }

Try / catch

try {
  List<Class<?>> path = surface.getAnyExposurePath(clazz);
} catch (IllegalArgumentException e) {
  // treat as 'not tracked in this surface'
}

Prevention

When it happens

Trigger: Calling getAnyExposurePath on a class that is not in the exposed set, or on an ApiSurface whose exposure graph was built without any matching root classes; programmatic use of ApiSurface where the query class was never added via exposedClass/exposure roots.

Common situations: Custom API-surface checks or test utilities built on org.apache.beam.sdk.util.ApiSurface querying classes excluded from the surface; root-class configuration missing the package containing the queried class.

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/4b2bd3b65bdd5d0e. Report an issue: GitHub.

Appendix: source

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

  }

  /** Returns exposed types in this set, including arrays and primitives as specified. */
  public Set<Class<?>> getExposedClasses() {
    return getExposedToExposers().keySet();
  }

  /**
   * Returns a path from an exposed class to a root class. There may be many, but this gives only
   * one.
   *
   * <p>If there are only cycles, with no path back to a root class, throws IllegalStateException.
   */
  public List<Class<?>> getAnyExposurePath(Class<?> exposedClass) {
    Set<Class<?>> excluded = Sets.newHashSet();
    excluded.add(exposedClass);
    List<Class<?>> path = getAnyExposurePath(exposedClass, excluded);
    if (path == null) {
      throw new IllegalArgumentException(
          "Class "
              + exposedClass
              + " has no path back to any root class."
              + " It should never have been considered exposed.");
    } else {
      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) {

View on GitHub (pinned to 12126d8942)