apache/iceberg · warning
max_concurrent_deletes only works with FileIOs that do not s
Error message
max_concurrent_deletes only works with FileIOs that do not support bulk deletes. This table is currently using {} which supports bulk deletes so the parameter will be ignored. See that IO's documentation to learn how to adjust parallelism for that particular IO's bulk delete. What it means
RemoveOrphanFilesProcedure logs this warning when `max_concurrent_deletes` is passed but the table's FileIO implements SupportsBulkOperations. Bulk-delete IOs manage their own delete parallelism internally, so the user-supplied concurrency knob is ignored rather than honored. It is a misconfiguration notice, not a failure — orphan file removal still proceeds.
Source
Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/procedures/RemoveOrphanFilesProcedure.java:176
if (olderThanMillis != null) {
boolean isTesting = Boolean.parseBoolean(spark().conf().get("spark.testing", "false"));
if (!isTesting) {
validateInterval(olderThanMillis);
}
action.olderThan(olderThanMillis);
}
if (location != null) {
action.location(location);
}
if (dryRun) {
action.deleteWith(file -> {});
}
if (maxConcurrentDeletes != null) {
if (table.io() instanceof SupportsBulkOperations) {
LOG.warn(
"max_concurrent_deletes only works with FileIOs that do not support bulk deletes. This "
+ "table is currently using {} which supports bulk deletes so the parameter will be ignored. "
+ "See that IO's documentation to learn how to adjust parallelism for that particular "
+ "IO's bulk delete.",
table.io().getClass().getName());
} else {
action.executeDeleteWith(executorService(maxConcurrentDeletes, "remove-orphans"));
}
}
if (fileListView != null) {
action.compareToFileList(spark().table(fileListView));
}
action.equalSchemes(equalSchemes);
action.equalAuthorities(equalAuthorities);
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Remove the max_concurrent_deletes argument from the procedure call; it has no effect.
- Tune the IO's own bulk-delete parallelism, e.g. set 's3.delete.threads' (S3FileIO) or the equivalent property documented for your FileIO.
- If per-delete concurrency is truly needed, switch the table to a non-bulk FileIO such as HadoopFileIO.
Example fix
// before
CALL iceberg.system.remove_orphan_files(table => 'db.t', max_concurrent_deletes => 16)
// after
ALTER TABLE db.t SET TBLPROPERTIES ('s3.delete.threads'='16');
CALL iceberg.system.remove_orphan_files(table => 'db.t') Defensive patterns
Strategy: validation
Validate before calling
FileIO io = table.io();
if (io instanceof SupportsBulkOperations) {
// don't pass max_concurrent_deletes; tune the IO's own thread property instead
} Type guard
boolean honorsMaxConcurrentDeletes = !(table.io() instanceof SupportsBulkOperations);
Prevention
- Check the table's FileIO class before setting delete concurrency options.
- Use IO-specific properties (e.g. s3.delete.threads) for bulk-delete parallelism.
- Log/treat ignored parameters as config drift in job validation.
When it happens
Trigger: Calling CALL iceberg.system.remove_orphan_files(...) with max_concurrent_deletes => N on a table whose io() is a bulk-capable FileIO (e.g. S3FileIO, which uses its own bulk delete thread pool).
Common situations: Copy-pasted SQL tuning advice written for HadoopFileIO applied to S3/GCS-backed tables; clusters where the catalog default FileIO changed between Iceberg versions.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- max_concurrent_deletes only works with FileIOs that do not s
- max_concurrent_deletes only works with FileIOs that do not s
- %s does not expose configuration properties
- Cannot parse order: parser is not an Iceberg ExtendedParser
- Cannot use catalog %s(%s): not a TableCatalog
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/059d312f0316f63c.
Report an issue: GitHub.