apache/iceberg · error · ValidationException
Class not found
Error message
Class %s not found : %s
What it means
ResolvingFileIO maps a location's scheme to a FileIO implementation class name via implFromLocation, then loads it reflectively with Class.forName. ValidationException is thrown when that class name cannot be found on the classpath, typically because the corresponding FileIO module (e.g. Hadoop) is not a dependency.
Solutions
- Add the shaded FileIO runtime jar for the location's scheme (iceberg-aws-bundle, iceberg-azure-bundle, iceberg-gcp-bundle, or iceberg-hadoop-mr) to the classpath.
- Verify the fully-qualified class name of any custom FileIO configured for the scheme is correct and present in the deployed artifact.
- Run the job with a fat/shaded jar that does not exclude io.* classes from relocation.
- Check that the scheme prefix in the location is spelled correctly so the expected implementation is resolved.
Example fix
// before spark-submit --packages org.apache.iceberg:iceberg-spark-runtime-4.1_2.13:... \ job.jar // s3:// paths fail: no S3FileIO on classpath // after spark-submit --packages org.apache.iceberg:iceberg-spark-runtime-4.1_2.13:...,org.apache.iceberg:iceberg-aws-bundle:... \ job.jar
Defensive patterns
Strategy: validation
Validate before calling
String cls = ioProps.getOrDefault(scheme(location) + ".impl", defaultFor(scheme(location)));
try {
Class.forName(cls);
} catch (ClassNotFoundException e) {
throw new IllegalStateException("FileIO class missing from classpath: " + cls +
". Add the matching iceberg-*-bundle jar.", e);
} Try / catch
try {
catalog.initialize("app", props);
} catch (ValidationException e) {
if (e.getMessage().contains("not found")) {
log.error("FileIO implementation missing: add iceberg-aws-bundle/iceberg-hadoop-mr to classpath");
}
throw e;
} Prevention
- Ship shaded runtime bundles (iceberg-aws-bundle, iceberg-azure-bundle, iceberg-gcp-bundle) for every scheme you read
- Add a startup smoke test that opens a file via ResolvingFileIO for each configured scheme
- Never rely on compile-scope deps for FileIO implementations in distributed jobs — use runtime/bundle jars
When it happens
Trigger: Calling ResolvingFileIO.ioClass(location) (directly or indirectly via usesHadoopFileIO) with a location whose mapped FileIO class is missing from the runtime classpath, e.g. an s3/hdfs/abfs location without the matching FileIO module loaded.
Common situations: Deploying a Spark/Flink job without the iceberg-aws or iceberg-hadoop-mr shaded jar; shading that excludes FileIO implementations; typos in custom FileIO class names in configuration; a location scheme (e.g. gcs) with no registered implementation.
Related errors
- Cannot initialize FileIO implementation
- Cannot cache changes: FileIO is null
- Cannot find class; alternatives
- Cannot find constructor for
- Cannot find method
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/5afe198d5d5898aa.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/io/ResolvingFileIO.java:244
Preconditions.checkState(
fileIO instanceof DelegateFileIO,
"FileIO does not implement DelegateFileIO: " + fileIO.getClass().getName());
return (DelegateFileIO) fileIO;
});
}
@VisibleForTesting
String implFromLocation(String location) {
return SCHEME_TO_FILE_IO.getOrDefault(scheme(location), FALLBACK_IMPL);
}
public Class<?> ioClass(String location) {
String fileIOClassName = implFromLocation(location);
try {
return Class.forName(fileIOClassName);
} catch (ClassNotFoundException e) {
throw new ValidationException("Class %s not found : %s", fileIOClassName, e.getMessage());
}
}
private static String scheme(String location) {
int colonPos = location.indexOf(":");
if (colonPos > 0) {
return location.substring(0, colonPos);
}
return null;
}
@SuppressWarnings({"checkstyle:NoFinalizer", "Finalize", "deprecation"})
@Override
protected void finalize() throws Throwable {
super.finalize();
if (!isClosed.get()) {
close();View on GitHub (pinned to 86d9c8fc54)