apache/beam · error · RuntimeException
Cannot detect classpath: classloader is null (is it the…
Error message
Cannot detect classpath: classloader is null (is it the bootstrap classloader?)
What it means
When no files-to-stage option is provided, getDependencies auto-detects the classpath using the classloader of the Environments class. Under the bootstrap classloader that getter returns null, so the service cannot detect the classpath and throws.
Solutions
- Explicitly set --filesToStage (PortablePipelineOptions) so auto-detection is skipped
- Launch the expansion service with a normal application classloader (java -jar / standard classpath)
- If embedding, pass your own classloader context or precompute classpath resources
- Check the launch command for -Xbootclasspath or custom launcher flags and remove them
Example fix
// before java -Xbootclasspath/a:beam.jar ... ExpansionServiceServer --port=8097 // after java -cp beam.jar:libs/* org.apache.beam.sdk.expansion.service.ExpansionService --port=8097 \ --filesToStage=/libs/*
Defensive patterns
Strategy: fallback
Validate before calling
if (options.as(PortablePipelineOptions.class).getFilesToStage() == null
&& Environments.class.getClassLoader() == null) {
options.as(PortablePipelineOptions.class).setFilesToStage(computeExplicitStageList());
} Try / catch
try { deps = provider.getDependencies(request); } catch (RuntimeException e) { if (e.getMessage().contains("classloader is null")) setFilesToStageExplicitly(); throw e; } Prevention
- Always pass --filesToStage in non-standard launchers
- Avoid -Xbootclasspath for the service
- Verify classloader with Environments.class.getClassLoader() != null in smoke tests
When it happens
Trigger: Running the expansion service on the boot classloader (e.g. -Xbootclasspath or unusual launcher) while PortablePipelineOptions.filesToStage is unset, forcing classpath auto-detection.
Common situations: Embedding the expansion service in a stripped-down JVM/container launch script; launching via a mechanism that bypasses the system classloader.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- Conflicting registrations for
- No classpath elements found.
- A transform cannot be initiated using the provided config…
- AutoValue generated class not found
- cannot rehydrate Coder.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/f6267fca6d9fb538.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/TransformProvider.java:209
// option
// is specified.
if (transformUniqueID != null
&& config.getDependencies().containsKey(transformUniqueID)
&& (!isManagedExpansion
|| options.as(ExpansionServiceOptions.class).getUseConfigDependenciesForManaged())) {
List<String> updatedDependencies =
config.getDependencies().get(transformUniqueID).stream()
.map(dependency -> dependency.getPath())
.collect(Collectors.toList());
return updatedDependencies;
}
List<String> filesToStage = options.as(PortablePipelineOptions.class).getFilesToStage();
if (filesToStage == null || filesToStage.isEmpty()) {
ClassLoader classLoader = Environments.class.getClassLoader();
if (classLoader == null) {
throw new RuntimeException(
"Cannot detect classpath: classloader is null (is it the bootstrap classloader?)");
}
filesToStage = PipelineResources.detectClassPathResourcesToStage(classLoader, options);
if (filesToStage.isEmpty()) {
throw new IllegalArgumentException("No classpath elements found.");
}
}
return filesToStage;
}
}
View on GitHub (pinned to 12126d8942)