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

  1. Explicitly set --filesToStage (PortablePipelineOptions) so auto-detection is skipped
  2. Launch the expansion service with a normal application classloader (java -jar / standard classpath)
  3. If embedding, pass your own classloader context or precompute classpath resources
  4. 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

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


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)