{"record":{"id":"a2235ec09e896564","repo":"apache/iceberg","slug":"max-concurrent-deletes-only-works-with-fileios-tha-a2235e","errorCode":null,"errorMessage":"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.","messagePattern":"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\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/procedures/ExpireSnapshotsProcedure.java","lineNumber":150,"sourceCode":"        \"max_concurrent_deletes should have value > 0, value: %s\",\n        maxConcurrentDeletes);\n\n    return modifyIcebergTable(\n        tableIdent,\n        table -> {\n          ExpireSnapshots action = actions().expireSnapshots(table);\n\n          if (olderThanMillis != null) {\n            action.expireOlderThan(olderThanMillis);\n          }\n\n          if (retainLastNum != null) {\n            action.retainLast(retainLastNum);\n          }\n\n          if (maxConcurrentDeletes != null) {\n            if (table.io() instanceof SupportsBulkOperations) {\n              LOG.warn(\n                  \"max_concurrent_deletes only works with FileIOs that do not support bulk deletes. This \"\n                      + \"table is currently using {} which supports bulk deletes so the parameter will be ignored. \"\n                      + \"See that IO's documentation to learn how to adjust parallelism for that particular \"\n                      + \"IO's bulk delete.\",\n                  table.io().getClass().getName());\n            } else {\n\n              action.executeDeleteWith(executorService(maxConcurrentDeletes, \"expire-snapshots\"));\n            }\n          }\n\n          if (snapshotIds != null) {\n            for (long snapshotId : snapshotIds) {\n              action.expireSnapshotId(snapshotId);\n            }\n          }\n\n          if (streamResult != null) {","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/procedures/ExpireSnapshotsProcedure.java#L132-L168","documentation":"A LOG.warn in ExpireSnapshotsProcedure.call: the max_concurrent_deletes parameter only controls thread pool size for FileIO implementations without bulk-delete support. When the table's FileIO implements SupportsBulkOperations (e.g. S3FileIO, GCSFileIO), parallelism is governed by the IO's own bulk-delete configuration and the procedure parameter is ignored.","triggerScenarios":"CALL catalog.system.expire_snapshots(..., max_concurrent_deletes => N) on a table whose io() instanceof SupportsBulkOperations (e.g. S3FileIO).","commonSituations":"Migrating from HadoopFileIO to S3FileIO and carrying over old tuning options; copy-pasted procedure calls across tables with different IOs.","solutions":["Remove max_concurrent_deletes for tables using bulk-capable IOs; it has no effect.","Tune the IO's own bulk-delete parallelism instead — e.g. S3FileIO's spark.s3.delete.batch-size / s3.delete.batch-size properties and the underlying client's concurrency settings.","Consult the specific FileIO implementation's documentation for its bulk-delete concurrency knobs."],"exampleFix":"// before\nCALL catalog.system.expire_snapshots(table => 'db.t', max_concurrent_deletes => 20)\n-- table io = S3FileIO (bulk deletes)\n// after\nCALL catalog.system.expire_snapshots(table => 'db.t')\n-- tune IO instead: SET TABLE PROPERTIES ('s3.delete.batch-size'='...') or client config","handlingStrategy":"validation","validationCode":"if (table.io() instanceof SupportsBulkOperations) {\n  // do not pass max_concurrent_deletes; tune IO bulk-delete settings instead\n}","typeGuard":"boolean ioSupportsBulkDeletes = table.io() instanceof org.apache.iceberg.io.SupportsBulkOperations;","tryCatchPattern":null,"preventionTips":["Conditionally pass max_concurrent_deletes only for non-bulk FileIOs","Learn your IO's bulk-delete concurrency knobs (e.g. s3.delete.batch-size)","Audit procedure call templates when migrating between FileIO implementations"],"tags":["spark","expire-snapshots","fileio","bulk-delete","ignored-parameter"],"backgroundTag":"ignored-configuration-parameter","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T21:17:11.552Z"}