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
- Check membership in the exposed set before requesting an exposure path for a class.
- Rebuild the ApiSurface with roots/predicates that include the queried class (see ApiSurface.of(rootClasses, predicates)).
- 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
- Verify membership in the exposed set before path lookups.
- Include the class's package in the surface roots/predicates.
- In tooling, model 'not exposed' as a normal result, not an exception path.
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
- Class has no path back to any root class. It should never…
- 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/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)