{"record":{"id":"4339b7b4a3442c30","repo":"apache/iceberg","slug":"failed-to-close-task-iterable-4339b7","errorCode":null,"errorMessage":"Failed to close task iterable","messagePattern":"Failed to close task iterable","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/source/SparkTable.java","lineNumber":258,"sourceCode":"    try (CloseableIterable<FileScanTask> tasks = scan.planFiles()) {\n      Map<Integer, Evaluator> evaluators = Maps.newHashMap();\n      StrictMetricsEvaluator metricsEvaluator = new StrictMetricsEvaluator(schema, deleteExpr);\n      return Iterables.all(\n          tasks,\n          task -> {\n            DataFile file = task.file();\n            PartitionSpec spec = task.spec();\n            Evaluator evaluator =\n                evaluators.computeIfAbsent(\n                    spec.specId(),\n                    specId ->\n                        new Evaluator(\n                            spec.partitionType(), Projections.strict(spec).project(deleteExpr)));\n            return evaluator.eval(file.partition()) || metricsEvaluator.eval(file);\n          });\n\n    } catch (IOException ioe) {\n      LOG.warn(\"Failed to close task iterable\", ioe);\n      return false;\n    }\n  }\n\n  @Override\n  public void deleteWhere(Predicate[] predicates) {\n    Expression deleteExpr = SparkV2Filters.convert(predicates);\n\n    if (deleteExpr == Expressions.alwaysFalse()) {\n      LOG.info(\"Skipping the delete operation as the condition is always false\");\n      return;\n    }\n\n    DeleteFiles deleteFiles =\n        table()\n            .newDelete()\n            .set(\"spark.app.id\", spark().sparkContext().applicationId())\n            .deleteFromRowFilter(deleteExpr);","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/source/SparkTable.java#L240-L276","documentation":"A WARN logged by SparkTable.canDeleteUsingMetadata when an IOException occurs while closing the CloseableIterable of task/file contexts used to evaluate whether a DELETE can be satisfied by metadata only (partition and metrics evaluation). The method returns false, so Spark falls back to a non-metadata (row-level or rewrite) delete — correctness is preserved, only the fast path is lost.","triggerScenarios":"canDeleteWhere -> canDeleteUsingMetadata opens a task iterable over table files; closing it throws IOException (underlying FileIO/manifest read error), or an earlier read inside the try-with-resources fails.","commonSituations":"Object-store transient errors while reading manifests/metrics; FileIO misconfiguration; network interruptions during scan planning.","solutions":["Retry the DELETE — the fallback delete path still works","Inspect the wrapped IOException cause for the underlying FileIO issue","Verify storage connectivity/credentials used by the table's FileIO"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  boolean ok = sparkTable.canDeleteWhere(predicates);\n  if (!ok) { /* fall back to row-level delete */ }\n} catch (Exception e) {\n  // fall back to rewrite/row-level delete path\n}","preventionTips":["Ensure stable connectivity to the table's object storage","Check FileIO configuration (endpoints, credentials) before DELETE workloads","Retry metadata-only deletes once on transient IOExceptions"],"tags":["spark","io-exception","delete"],"backgroundTag":"file-close-failed","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}