Repository: kestra-io/kestra
Issue: Invalid retry configuration could fail the Worker
Labels: bug

### Explain the bug

The following flow will fail the worker:

```yaml
id: flow_2
namespace: edmcode
tasks:
  - id: "bash"
    type: "io.kestra.core.tasks.scripts.Bash"
    inputFiles:
      script.sh: |
        #!/bin/bash
        n=$(date +"%M")
        if ((n % 2 == 0)); then
            echo "$n is even"
            ((result = 1 / 0))
        else
            echo "$n is odd"
        fi
    commands:
    - /bin/bash script.sh
    retry:
      type: constant
      interval: PT1M
      maxAttempt: 3
      maxDuration: PT1M
```

### Environment Information

- Kestra Version: 0.13
- Operating System and Java Version (if not using Kestra Docker image):


Issue comments:

Pull request review comments:

Patch that resolved the issue:
diff --git a/core/src/main/java/io/kestra/core/runners/Worker.java b/core/src/main/java/io/kestra/core/runners/Worker.java
index 7c8d4916df..14bfb1a781 100644
--- a/core/src/main/java/io/kestra/core/runners/Worker.java
+++ b/core/src/main/java/io/kestra/core/runners/Worker.java
@@ -36,6 +36,7 @@
 import lombok.Synchronized;
 import lombok.extern.slf4j.Slf4j;
 import net.jodah.failsafe.Failsafe;
+import net.jodah.failsafe.RetryPolicy;
 import net.jodah.failsafe.Timeout;
 import org.slf4j.Logger;
 
@@ -345,9 +346,25 @@ private WorkerTaskResult run(WorkerTask workerTask, Boolean cleanUp) throws Queu
 
         AtomicReference<WorkerTask> current = new AtomicReference<>(workerTask);
 
+        // creating the retry can fail
+        RetryPolicy<WorkerTask> workerTaskRetryPolicy;
+        try {
+            workerTaskRetryPolicy = AbstractRetry.retryPolicy(workerTask.getTask().getRetry());
+        } catch(IllegalStateException e) {
+            WorkerTask finalWorkerTask = workerTask.fail();
+            WorkerTaskResult workerTaskResult = new WorkerTaskResult(finalWorkerTask);
+            RunContext runContext = workerTask
+                .getRunContext()
+                .forWorker(this.applicationContext, workerTask);
+
+            runContext.logger().error("Exception while trying to build the retry policy", e);
+            this.workerTaskResultQueue.emit(workerTaskResult);
+            return workerTaskResult;
+        }
+
         // run
         WorkerTask finalWorkerTask = Failsafe
-            .with(AbstractRetry.<WorkerTask>retryPolicy(workerTask.getTask().getRetry())
+            .with(workerTaskRetryPolicy
                 .handleResultIf(result -> result.getTaskRun().lastAttempt() != null &&
                         result.getTaskRun().lastAttempt().getState().getCurrent() == State.Type.FAILED &&
                         !killedExecution.contains(result.getTaskRun().getExecutionId())


Test patch:
diff --git a/core/src/test/java/io/kestra/core/runners/RetryTest.java b/core/src/test/java/io/kestra/core/runners/RetryTest.java
index c0b889540c..2371c20179 100644
--- a/core/src/test/java/io/kestra/core/runners/RetryTest.java
+++ b/core/src/test/java/io/kestra/core/runners/RetryTest.java
@@ -46,4 +46,13 @@ void retryFailed() throws TimeoutException {
         assertThat(execution.getTaskRunList().get(0).getAttempts(), hasSize(5));
         assertThat(execution.getState().getCurrent(), is(State.Type.FAILED));
     }
+
+    @Test
+    void retryInvalid() throws TimeoutException {
+        Execution execution = runnerUtils.runOne(null, "io.kestra.tests", "retry-invalid");
+
+        assertThat(execution.getTaskRunList(), hasSize(1));
+        assertThat(execution.getTaskRunList().get(0).getAttempts(), nullValue());
+        assertThat(execution.getState().getCurrent(), is(State.Type.FAILED));
+    }
 }
diff --git a/core/src/test/resources/flows/valids/retry-invalid.yml b/core/src/test/resources/flows/valids/retry-invalid.yml
new file mode 100644
index 0000000000..4343a99878
--- /dev/null
+++ b/core/src/test/resources/flows/valids/retry-invalid.yml
@@ -0,0 +1,12 @@
+id: retry-invalid
+namespace: io.kestra.tests
+
+tasks:
+  - id: log
+    type: io.kestra.core.tasks.log.Log
+    message: Hello World!
+    retry:
+      type: constant
+      interval: PT0.250S
+      maxAttempt: 5
+      maxDuration: PT0.250S
\ No newline at end of file