{"record":{"id":"64bf0b4efb677b81","repo":"apache/iceberg","slug":"failed-to-close-task-iterable-64bf0b","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.0/spark/src/main/java/org/apache/iceberg/spark/source/SparkTable.java","lineNumber":444,"sourceCode":"      StrictMetricsEvaluator metricsEvaluator =\n          new StrictMetricsEvaluator(SnapshotUtil.schemaFor(table(), scanBranch), deleteExpr);\n\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        icebergTable\n            .newDelete()\n            .set(\"spark.app.id\", sparkSession().sparkContext().applicationId())\n            .deleteFromRowFilter(deleteExpr);","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/source/SparkTable.java#L426-L462","documentation":"SparkTable.canDeleteUsingMetadata evaluates whether a DELETE can be satisfied by metadata only (dropping whole files). While closing the task's CloseableIterable, an IOException occurred; the method logs it and returns false, so the delete falls back to a rewrite (copy-on-write) plan. Correctness is preserved, only efficiency is lost.","triggerScenarios":"During metadata-only delete planning, closing the per-task iterable (e.g. after reading file partitions/metrics) throws IOException, caught at the end of canDeleteUsingMetadata.","commonSituations":"Underlying storage hiccup while closing manifest/task streams; credentials or network issues mid-planning; Hadoop FileSystem deprecation warnings surfacing as IO errors on close.","solutions":["No action required — delete falls back to copy-on-write and still succeeds.","Check storage connectivity/permissions if the warning recurs.","If metadata-only deletes matter for performance, resolve the underlying IO error so planning completes."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// deleteWhere still succeeds via CoW fallback; retry the DELETE if metadata-only behavior is required","preventionTips":["Ensure stable storage connectivity during DELETE planning.","Retry DELETE operations if the warning appears and you need metadata-only deletes.","Monitor for repeated warnings as a sign of flaky object storage."],"tags":["spark","delete","metadata-delete","io"],"backgroundTag":"file-read-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"}