apache/iceberg · error · ClassNotFoundException
Cannot find class; alternatives: ${classNames}
Error message
Cannot find class; alternatives: ${classNames} What it means
DynClasses.Builder.buildChecked() throws ClassNotFoundException when none of the candidate class names could be loaded and nullOk is false. It is the checked variant: callers are forced to handle the missing-class case. The message lists every alternative name that was tried.
Source
Thrown at common/src/main/java/org/apache/iceberg/common/DynClasses.java:104
*
* @return this Builder for method chaining
*/
public Builder orNull() {
this.nullOk = true;
return this;
}
/**
* Returns the first implementation or throws ClassNotFoundException if one was not found.
*
* @param <S> Java superclass
* @return a {@link Class} for the first implementation found
* @throws ClassNotFoundException if no implementation was found
*/
@SuppressWarnings("unchecked")
public <S> Class<? extends S> buildChecked() throws ClassNotFoundException {
if (!nullOk && foundClass == null) {
throw new ClassNotFoundException(
"Cannot find class; alternatives: " + Joiner.on(", ").join(classNames));
}
return (Class<? extends S>) foundClass;
}
/**
* Returns the first implementation or throws RuntimeException if one was not found.
*
* @param <S> Java superclass
* @return a {@link Class} for the first implementation found
* @throws RuntimeException if no implementation was found
*/
@SuppressWarnings("unchecked")
public <S> Class<? extends S> build() {
if (!nullOk && foundClass == null) {
throw new RuntimeException(
"Cannot find class; alternatives: " + Joiner.on(", ").join(classNames));
}View on GitHub (pinned to 86d9c8fc54)
Solutions
- Check the listed alternatives against the actual classpath; add the jar that provides one of them (e.g. the correct Spark/Hive version).
- Verify the fully-qualified class names — package renames across versions are the usual culprit.
- Call nullOk(true) if absence is acceptable, and handle the null Class explicitly.
- Use build() (RuntimeException) or a default impl(...) that always matches to avoid a hard failure.
Example fix
// before
Class<?> cls = DynClasses.builder().impl("org.apache.spark.sql.catalyst.OldClass").buildChecked();
// after
Class<?> cls = DynClasses.builder()
.impl("org.apache.spark.sql.catalyst.NewClass")
.impl("org.apache.spark.sql.catalyst.OldClass")
.buildChecked(); Defensive patterns
Strategy: try-catch
Validate before calling
for (String name : new String[]{"com.example.ImplA", "com.example.ImplB"}) {
try {
Class.forName(name);
return; // at least one candidate exists
} catch (ClassNotFoundException ignored) { }
}
throw new IllegalStateException("None of the candidate classes are on the classpath; add the required dependency"); Try / catch
try {
Class<?> cls = DynClasses.builder().impl("com.example.ImplA").impl("com.example.ImplB").buildChecked();
} catch (ClassNotFoundException e) {
// no candidate found: log the alternatives and fall back or fail fast
} Prevention
- List candidates for every known version of the target library
- Fail fast at startup rather than lazily in a job
- Check the classpath (mvn dependency:tree / spark.jars) for the jar providing the class
- Use nullOk(true) only when absence genuinely has a supported fallback
When it happens
Trigger: Calling DynClasses.builder().impl("a.B").impl("c.D").buildChecked() where every impl name fails to load (class absent, wrong name, or classloader can't see it).
Common situations: Detecting engine/runtime versions by trying class names (e.g. Spark 2 vs 3 classes) on a runtime that has neither; typos in fully-qualified names; shaded/missing jars on the classpath.
Related errors
- Cannot load class %s, it does not exist in the classpath
- Cannot load class %s, it does not exist in the classpath
- Cannot find field from candidates: ${candidates}
- Cannot find method: ${name}
- Cannot initialize Catalog implementation %s: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/420b7d56f73d4106.
Report an issue: GitHub.