# Is having retry for both Worklfow and its activity redundant?

**URL:** <https://community.temporal.io/t/is-having-retry-for-both-worklfow-and-its-activity-redundant/2889>\
**Category:** Community Support\
**Tags:** java-sdk\
**Created:** [September 9, 2021, 8:53am UTC](https://community.temporal.io/t/is-having-retry-for-both-worklfow-and-its-activity-redundant/2889 "2021-09-09T08:53:49Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Vikas\_NS](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/vikas_ns/32/1210_2.png) [@Vikas\_NS](https://community.temporal.io/u/Vikas_NS)\
**Post date:** [September 9, 2021, 8:53am UTC](https://community.temporal.io/t/is-having-retry-for-both-worklfow-and-its-activity-redundant/2889/1 "2021-09-09T08:53:50Z")

</div>

**Questions**

1. I have an activity which makes network call and a workflow that holds this activity. Does having 20 max retries for both the workflow and the activity inside the workflow result in total of 20 x 20 network call? I mean, 20 times of activity failure constitutes 1 workflow failure. So 20 Workflow failure should result in 20 x 20 = 400 retries of network call?

2. I have 2 activities which make 2 different network calls and a workflow that holds these two activities. Both the activites and the workflow have max 20 retries. In the scenario where the first activity is successfull, and the second one keeps failing, after 20 retries of 2nd activity, the activity gives up . Now when the workflow kicks in for the 2nd time, will the first activity which was successfull be executed again? or is it just the failed activity be executed?

3. In what situations should we have retries for both workflow and activity?

---

<div class="post-metadata">

**Author:** ![tihomir](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/tihomir/32/6580_2.png) [@tihomir](https://community.temporal.io/u/tihomir)\
**Post date:** [September 9, 2021, 1:34pm UTC](https://community.temporal.io/t/is-having-retry-for-both-worklfow-and-its-activity-redundant/2889/2 "2021-09-09T13:34:26Z")

</div>

1, 2: On each workflow retry, it is executed from the beginning which means already executed activities will be re-executed on the new run. Generally you do not want to fail your workflows on “intermittent” errors, for example your activity errors which could be fixed via new deployment or code changes/fixes.

3: Generally failing workflow execution is not the best idea. One use case for workflow retries is when you want to retry a workflow on unknown failures. You should however if possible make sure your workflows do not fail on known errors. In the case where you do want to retry on a known failure you should still handle that error in your workflow and have the control how to retry (use continueasnew for example explicitly).

---

<div class="post-metadata">

**Author:** ![Vikas\_NS](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/vikas_ns/32/1210_2.png) [@Vikas\_NS](https://community.temporal.io/u/Vikas_NS)\
**Post date:** [September 13, 2021, 8:41am UTC](https://community.temporal.io/t/is-having-retry-for-both-worklfow-and-its-activity-redundant/2889/3 "2021-09-13T08:41:16Z")

</div>

Tihomir,

I’m finding a bit hard to understand workflow retry.

Please check the attached image.

I’m throwing a excpetion to fail the child workflow.

The child workflow fails and retries.

Below is my child worklfow options

```auto
ChildWorkflowOptions workflowOptions =
          ChildWorkflowOptions.newBuilder()
              .setRetryOptions(RetryOptions.newBuilder().setMaximumAttempts(3).build())
              .build();
      GreetingChild child = Workflow.newChildWorkflowStub(GreetingChild.class, workflowOptions);

```

**Questions**

1. Event though I have the max attemps set to 3, the child workflow seems to be retrying more than that. I have added a log just before I throw the exception. This log is appearing more than 3 times.

2. After the child workflow fails, based on your comments, for the next retry, I was excpecting a new workflow with different run id to be created. But looks like nothing like that happened

 ![image](https://us1.discourse-cdn.com/flex016/uploads/temporal/original/2X/7/75cc0a37897c55d7a8e6c763460c0aa4b2262c76.png)

---

<div class="post-metadata">

**Author:** ![tihomir](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/tihomir/32/6580_2.png) [@tihomir](https://community.temporal.io/u/tihomir)\
**Post date:** [September 13, 2021, 2:24pm UTC](https://community.temporal.io/t/is-having-retry-for-both-worklfow-and-its-activity-redundant/2889/4 "2021-09-13T14:24:34Z")

</div>

Unknown exceptions in your child workflow code which are set in [setFailWorkflowExceptionTypes](https://github.com/temporalio/sdk-java/blob/master/temporal-sdk/src/main/java/io/temporal/worker/WorkflowImplementationOptions.java#L68) are converted to ApplicationFailure. Otherwise the workflow task is failed and your workflow gets blocked (the exception is treated as a bug that can be fixed on a future deployment which is what you are seeing in your test).

If you want to throw checked exceptions not in that list, you can use:

ApplicationFailure.newFailure  
or  
ApplicationFailure.newNonRetryableFailure

so in the HelloChild sample you are working off you can do in your child workflow:

`throw ApplicationFailure.newFailure("Failing child workflow", "simulated");`

(note you do not need that @SneakyThrows Lombok annotation)

and in your workflow you could do:

```auto
try {
        return child.composeGreeting("Hello", name);
        // return Async.function(child::composeGreeting, "Hello", name).get();
      } catch (ChildWorkflowFailure failure) {
        Workflow.getLogger(GreetingWorkflowImpl.class)
            .error(failure.getCause().getMessage());
        ...
      }

```

This should honor your ChildWorkflowOptions-\>RetryOptions and you should see the child workflow being retried 3 times before you catch the error in your workflow.

Child workflow invocations always throw ChildWorkflowFailure and you can get the original failure in the cause.

Also note that workflow retries only apply if you define RetryOptions in your WorkflowOptions.  
So if you in your main method of the HelloChild Sample define:

```auto
GreetingWorkflow workflow =
        client.newWorkflowStub(
            GreetingWorkflow.class,
            WorkflowOptions.newBuilder()
                .setRetryOptions(RetryOptions.newBuilder().setMaximumAttempts(2).build())
                .setWorkflowId(WORKFLOW_ID)
                .setTaskQueue(TASK_QUEUE)
                .build());

```

and don’t catch the ChildWorkflowException in your parent workflow code, you should see your workflow being retried ( and have the ContinuedAsNew status as you pointed out).

---

<div class="post-metadata">

**Author:** ![Vikas\_NS](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/vikas_ns/32/1210_2.png) [@Vikas\_NS](https://community.temporal.io/u/Vikas_NS)\
**Post date:** [September 20, 2021, 7:53am UTC](https://community.temporal.io/t/is-having-retry-for-both-worklfow-and-its-activity-redundant/2889/5 "2021-09-20T07:53:17Z")

</div>

Got it.  
Thankyou Tihomir.

Could you please share a snippet on ussing setFailWorkflowExceptionTypes ? I want to know on which object I need to call this method.

---

<div class="post-metadata">

**Author:** ![tihomir](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/tihomir/32/6580_2.png) [@tihomir](https://community.temporal.io/u/tihomir)\
**Post date:** [September 20, 2021, 1:16pm UTC](https://community.temporal.io/t/is-having-retry-for-both-worklfow-and-its-activity-redundant/2889/6 "2021-09-20T13:16:17Z")

</div>

```auto
WorkflowImplementationOptions implementationOptions = WorkflowImplementationOptions.newBuilder()
            .setFailWorkflowExceptionTypes(Throwable.class)
            .build();

....

worker.registerWorkflowImplementationType(implementationOptions, <WorkflowClass>.class);

```

for example if you want to fail the workflow on any exceptions for the particular WorkflowClass

---

<div class="post-metadata">

**Author:** ![Vikas\_NS](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/vikas_ns/32/1210_2.png) [@Vikas\_NS](https://community.temporal.io/u/Vikas_NS)\
**Post date:** [November 20, 2021, 11:47am UTC](https://community.temporal.io/t/is-having-retry-for-both-worklfow-and-its-activity-redundant/2889/7 "2021-11-20T11:47:42Z")

</div>

> [@tihomir](#):
>
> Otherwise the workflow task is failed and your workflow gets blocked (the exception is treated as a bug that can be fixed on a future deployment which is what you are seeing in your test)

Hi Tihomir,  
What do you mean when you say workflow gets blocked?

Will the retry happen infinitely?  
How do I control the retries?

---

<div class="post-metadata">

**Author:** ![Vikas\_NS](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/vikas_ns/32/1210_2.png) [@Vikas\_NS](https://community.temporal.io/u/Vikas_NS)\
**Post date:** [November 20, 2021, 2:59pm UTC](https://community.temporal.io/t/is-having-retry-for-both-worklfow-and-its-activity-redundant/2889/8 "2021-11-20T14:59:55Z")

</div>

> [@tihomir](#):
>
> This should honor your ChildWorkflowOptions-\>RetryOptions and you should see the child workflow being retried 3 times before you catch the error in your workflow.

Will activity failure exception produce the same effect?

Want to know which are all the default temporal exceptions that produce this behavior.?

---

<div class="post-metadata">

**Author:** ![tihomir](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/tihomir/32/6580_2.png) [@tihomir](https://community.temporal.io/u/tihomir)\
**Post date:** [November 20, 2021, 6:09pm UTC](https://community.temporal.io/t/is-having-retry-for-both-worklfow-and-its-activity-redundant/2889/9 "2021-11-20T18:09:25Z")

</div>

> What do you mean when you say workflow gets blocked?  
> Will the retry happen infinitely?  
> How do I control the retries?

Workflow task is retried up to your defined workflow run/execution timeout, at which point the workflow times out.

> Will activity failure exception produce the same effect?

Do you mean if an activity inside the child workflow fails? Yes if it fails, and after the activity exhausted its retries, it will be converted to ActivityFailure. This error since it happened inside a child workflow can be caught inside your workflow code as a ChildWorkflowFailure, that includes ActivityFailure as its cause, which will include the original exception (let’s say a NPE) as it’s cause.

> Want to know which are all the default temporal exceptions that produce this behavior.?

All classes that extend TemporalFailure:

TimeoutFailure  
ActivityFailure  
ApplicationFailure  
CancelledFailure  
ChildWorkflowFailure  
ServerFailure  
TerminatedFailure

---

<div class="post-metadata">

**Author:** ![Vikas\_NS](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/vikas_ns/32/1210_2.png) [@Vikas\_NS](https://community.temporal.io/u/Vikas_NS)\
**Post date:** [November 21, 2021, 1:43pm UTC](https://community.temporal.io/t/is-having-retry-for-both-worklfow-and-its-activity-redundant/2889/10 "2021-11-21T13:43:27Z")

</div>

> [@tihomir](#):
>
> Workflow task is retried up to your defined workflow run/execution timeout, at which point the workflow times out.

How about frequency? I don’t want it to retry very frequently and use up resources.? Is it possible to control that?

---

<div class="post-metadata">

**Author:** ![maxim](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/maxim/32/8_2.png) [@maxim](https://community.temporal.io/u/maxim)\
**Post date:** [November 21, 2021, 8:29pm UTC](https://community.temporal.io/t/is-having-retry-for-both-worklfow-and-its-activity-redundant/2889/11 "2021-11-21T20:29:29Z")

</div>

> How about frequency? I don’t want it to retry very frequently and use up resources.? Is it possible to control that?

Currently, it is retried every workflow task timeout. We do have plans to add exponential retry options to this scenario.
