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
- Only call getAnyExposurePath on classes returned by the surface's exposedClasses()/contains logic — verify membership first.
- Ensure the root classes supplied when building the ApiSurface actually cover the package of the class being queried.
- 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
- Query exposure paths only for classes known to be in the surface.
- Keep root-class configuration in sync with the packages you analyze.
- Build ApiSurface instances once per analysis and reuse; don't query across instances.
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
- Class is not exposed.
- Buffer counter not initialized for UUID:
- Processing elements map not initialized for UUID:
- Thread pool not initialized for UUID:
- Unexpected mode: " + mode
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)