Managing errors in a distributed system are usually tedious. Infinitic makes our life easier, by automatically keeping trace of the chain of errors. Infinitic even let us code the reaction to errors directly from the workflow!

Error when processing a task

Tasks are processed within workers. If an exception is thrown while processing a task, the exception is caught by the worker and the task is automatically retried according to the retry policy.

Error when processing a task

Once all retries have failed, the worker tells the workflow the task has failed with a WorkerException. This exception has the properties below:

workerNameStringname of the worker where the exception occured
nameStringexception name
messageStringexception message
stackTraceToStringStringstring version of the exception stacktrace
causeWorkerException(optional) exception cause

Serializing exceptions is error-prone. That's why we "normalize" them into a WorkerException format.

What happens in the workflow depends on whether it is waiting for the task to be completed or not:

If the workflow expects the task result

This is the case when we dispatch a task synchronously and also when we are waiting the result of a Deferred<T>. In this case, a FailedTaskException is thrown inside the workflow with the properties below:

taskNameStringtask name
taskIdStringtask id
methodNameStringmethod called
workerExceptionWorkerExceptiontask failure cause

Error when processing a sync task

Also, if another client or workflow expects the result of this workflow, it will see a FailedWorkflowException:

Error when processing a sync task

FailedWorkflowException has the properties below:

workflowNameStringworkflow name
workflowIdStringworkflow id
methodNameStringmethod called
methodRunIdStringmethod run id
deferredExceptionDeferredExceptionworkflow failure cause

In the example above, deferredException would be a FailedTaskException.

If the workflow does not expect the task result

This is the case, when we dispatch a task asynchronously, or for a task in another method running in parallel.

Error when processing an async task

In this case, the task is failed, but the workflow continues without error, as the failed task is not on the main path. But if the workflow waits fot the result later, then a FailedTaskException will be thrown then:

Error when processing an async task

Errors due to cancellation and more

We have seen that a failure of a synchronous task will throw a FailedTaskException. Also the failure of a synchronous child-workflow will throw a FailedWorkflowException. There are similar errors due to cancelation, and some other cases:

NameWhen it happens
FailedTaskExceptionthe task has failed. A task has failed only after all planed retries have failed.
CanceledTaskExceptionthe task has been canceled.
FailedWorkflowExceptionthe targeted workflow has a failed synchronous task / child-workflow.
CanceledWorkflowExceptionthe targeted workflow has been canceled.
UnknownWorkflowExceptionthe targeted workflow has never existed or if it is already completed or canceled. This can happen when dispatching a method on a stub created by getWorkflowById.
FailedWorkflowTaskExceptionan error occured directly from the code of the workflow.

All those exceptions inherit from io.infinitic.exceptions.DeferredException

Try/catch in workflows

We may want to react to a DeferredException or one of its subclass. For example, if we want to react to the inability to complete a task with new tasks:

Try/catch in workflows should be used only for situations when we need to react to unexpected failures. If we expect some failures in our task, a better practice is to catch them directly in the task and send back a status object as a result.

DeferredException and its sub-classes are the only relevant exceptions in workflows. We must not catch any other exception.

If a DeferredException has been caught in a workflow, it can not be resumed anymore (see below).


New version 0.11.2!