{"record":{"id":"775c9bbf728eba07","repo":"apache/iceberg","slug":"failed-to-close-table-loader-775c9b","errorCode":null,"errorMessage":"Failed to close table loader","messagePattern":"Failed to close table loader","errorType":"exception","errorClass":"UncheckedIOException","httpStatus":null,"severity":"warning","filePath":"flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/source/IcebergSource.java","lineNumber":166,"sourceCode":"   */\n  private List<IcebergSourceSplit> planSplitsForBatch(String threadName) {\n    if (batchSplits != null) {\n      return batchSplits;\n    }\n\n    ExecutorService workerPool =\n        ThreadPools.newFixedThreadPool(threadName, scanContext.planParallelism());\n    try (TableLoader loader = tableLoader.clone()) {\n      loader.open();\n      this.batchSplits =\n          FlinkSplitPlanner.planIcebergSourceSplits(loader.loadTable(), scanContext, workerPool);\n      LOG.info(\n          \"Discovered {} splits from table {} during job initialization\",\n          batchSplits.size(),\n          tableName);\n      return batchSplits;\n    } catch (IOException e) {\n      throw new UncheckedIOException(\"Failed to close table loader\", e);\n    } finally {\n      workerPool.shutdown();\n    }\n  }\n\n  @Override\n  public Boundedness getBoundedness() {\n    return scanContext.isStreaming() ? Boundedness.CONTINUOUS_UNBOUNDED : Boundedness.BOUNDED;\n  }\n\n  @Override\n  public SourceReader<T, IcebergSourceSplit> createReader(SourceReaderContext readerContext) {\n    IcebergSourceReaderMetrics metrics =\n        new IcebergSourceReaderMetrics(readerContext.metricGroup(), tableName);\n    return new IcebergSourceReader<>(\n        emitter, metrics, readerFunction, splitComparator, readerContext);\n  }\n","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/source/IcebergSource.java#L148-L184","documentation":"IcebergSource.planSplitsForBatch plans all batch splits during job initialization inside a try-with-resources on the TableLoader; if closing the TableLoader throws IOException, it is wrapped into an UncheckedIOException with this message. The worker pool is shut down in a finally block regardless. It indicates a failure releasing the table's FileIO resources after batch planning completed.","triggerScenarios":"Calling IcebergSource.splits (batch mode) where tableLoader.close() throws IOException after batch split discovery succeeds — e.g., Hadoop FileIO close failing on the underlying filesystem handle.","commonSituations":"Hadoop FileSystem close errors in long-lived jobs; interrupted close during job cancellation; misconfigured Hadoop filesystem caches releasing native resources.","solutions":["Inspect the wrapped IOException cause; it usually reflects an underlying filesystem close problem that is often benign — verify planning output was produced.","Check Hadoop/HDFS client configuration and versions for known close/handle-leak bugs; align Hadoop client versions.","Avoid forced cancellation during initialization; let batch planning and close finish.","If reproducible, report with the cause stack; the planned splits are valid, so a retry typically succeeds."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  List<IcebergSourceSplit> splits = source.splits(...);\n} catch (UncheckedIOException e) {\n  if (e.getCause() != null && isBenignCloseFailure(e.getCause())) {\n    LOG.warn(\"Table loader close failed after successful planning; ignoring\", e);\n  } else { throw e; }\n}","preventionTips":["Don't cancel jobs during batch initialization; wait for planning to finish.","Keep Hadoop client versions consistent to avoid FileSystem close bugs.","Log and classify close-time IOExceptions separately from planning failures."],"tags":["flink","io","resource-cleanup","table-loader"],"backgroundTag":"file-open-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"}