{"record":{"id":"394e82b58e2befc8","repo":"apache/iceberg","slug":"interrupted-while-waiting-for-tasks-to-finish","errorCode":null,"errorMessage":"Interrupted while waiting for tasks to finish","messagePattern":"Interrupted while waiting for tasks to finish","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/util/Tasks.java","lineNumber":524,"sourceCode":"              }\n              throw (Error) cause;\n            }\n\n            if (cause != null) {\n              uncaught.add(e);\n            }\n\n            LOG.warn(\"Task threw uncaught exception\", cause);\n          }\n        }\n\n        return uncaught;\n\n      } else {\n        try {\n          Thread.sleep(10);\n        } catch (InterruptedException e) {\n          LOG.warn(\"Interrupted while waiting for tasks to finish\", e);\n\n          for (Future<?> future : futures) {\n            future.cancel(true);\n          }\n          Thread.currentThread().interrupt();\n          throw new RuntimeException(e);\n        }\n      }\n    }\n  }\n\n  /** A range, [ 0, size ) */\n  private static class Range implements Iterable<Integer> {\n    private int size;\n\n    Range(int size) {\n      this.size = size;\n    }","sourceCodeStart":506,"sourceCodeEnd":542,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/util/Tasks.java#L506-L542","documentation":"Tasks.waitFor() polls task progress with 10ms sleeps; the sleeping thread was interrupted before all futures finished. All in-flight futures are cancelled with cancel(true), the interrupt flag is restored, and a RuntimeException wrapping InterruptedException is thrown.","triggerScenarios":"The thread waiting on task completion is interrupted mid-run — executor shutdownNow(), Spark/Flink task cancellation, or manual Thread.interrupt() while Tasks-based parallel work (e.g. commits, deletes) is still executing.","commonSituations":"Cancelling a long-running Spark stage that performs Iceberg commits; executor lifecycle mismanagement in custom actions; operator-triggered job restarts.","solutions":["Avoid interrupting threads running Tasks.waitFor() until commits complete; cancel at a safe boundary","Check that the owning executor is not shut down prematurely (shutdownNow vs shutdown after task completion)","Handle the RuntimeException as cancellation: expect partial work and re-run idempotently","Increase task-level retry/failure handling so cancellations are less frequent"],"exampleFix":"// before\nexecutor.shutdownNow(); // interrupts in-flight Tasks.waitFor\n// after\nexecutor.shutdown();\nexecutor.awaitTermination(5, TimeUnit.MINUTES);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  Tasks.foreach(items).executeWith(pool).stopOnFailure().run();\n} catch (RuntimeException e) {\n  if (e.getCause() instanceof InterruptedException) {\n    // futures were cancelled(true); re-run idempotently if needed\n    handleCancellation();\n  }\n}","preventionTips":["Avoid interrupting threads performing Iceberg commits mid-flight","Use executor.shutdown() + awaitTermination instead of shutdownNow() during work","Design tasks to be idempotent so cancellation recovery is safe"],"tags":["java","interruption","concurrency","task-cancellation"],"backgroundTag":"invalid-state-transition","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"}