Azure Functions error handling and retries

Handling errors in Azure Functions is important to avoid lost data, missed events, and to monitor the health of your application. It's also important to understand the retry behaviors of event-based triggers.

This article describes general strategies for error handling and the available retry strategies.

Important

The retry policy support in the runtime for triggers other than Timer and Event Hubs is being removed after this feature becomes generally available (GA). Preview retry policy support for all triggers other than Timer and Event Hubs will be removed in October 2022.

Handling errors

Errors raised in an Azure Functions can come from any of the following origins:

  • Use of built-in Azure Functions triggers and bindings.
  • Calls to APIs of underlying Azure services.
  • Calls to REST endpoints.
  • Calls to client libraries, packages, or third-party APIs.

Good error handling practices are important to avoid loss of data or missed messages. This section describes some recommended error handling practices with links to more information.

Enable Application Insights

Azure Functions integrates with Application Insights to collect error data, performance data, and runtime logs. You should use Application Insights to discover and better understand errors occurring in your function executions. To learn more, see Monitor Azure Functions.

Use structured error handling

Capturing and logging errors is critical to monitoring the health of your application. The top-most level of any function code should include a try/catch block. In the catch block, you can capture and log errors. For information about what errors might be raised by bindings, see Binding error codes.

Plan your retry strategy

Several Functions bindings extensions provide built-in support for retries. In addition, the runtime lets you define retry policies for Timer and Event Hubs triggered functions. To learn more, see Retries. For triggers that don't provide retry behaviors, you may want to implement your own retry scheme.

Design for idempotency

The occurrence of errors when processing data can be a problem for your functions, especially when processing messages. You need to consider what happens when the error occurs and how to avoid duplicate processing. To learn more, see Designing Azure Functions for identical input.

Retries

There are two kinds of retries available for your functions: built-in retry behaviors of individual trigger extensions and retry policies. The following table indicates which triggers support retries and where the retry behavior is configured. It also links to more information about errors coming from the underlying services.

Trigger/binding Retry source Configuration
Azure Cosmos DB n/a Not configurable
Blob Storage Binding extension host.json
Event Grid Binding extension Event subscription
Event Hubs Retry policies Function-level
Queue Storage Binding extension host.json
RabbitMQ Binding extension Dead letter queue
Service Bus Binding extension Dead letter queue
Timer Retry policies Function-level

Retry policies

Starting with version 3.x of the Azure Functions runtime, you can define a retry policies for Timer and Event Hubs triggers that are enforced by the Functions runtime. The retry policy tells the runtime to rerun a failed execution until either successful completion occurs or the maximum number of retries is reached.

A retry policy is evaluated when a Timer or Event Hubs triggered function raises an uncaught exception. As a best practice, you should catch all exceptions in your code and rethrow any errors that you want to result in a retry. Event Hubs checkpoints won't be written until the retry policy for the execution has completed. Because of this behavior, progress on the specific partition is paused until the current batch has completed.

Retry strategies

There are two retry strategies supported by policy that you can configure:

A specified amount of time is allowed to elapse between each retry.

Max retry counts

You can configure the maximum number of times function execution is retried before eventual failure. The current retry count is stored in memory of the instance. It's possible that an instance has a failure between retry attempts. When an instance fails during a retry policy, the retry count is lost. When there are instance failures, the Event Hubs trigger is able to resume processing and retry the batch on a new instance, with the retry count reset to zero. Timer trigger doesn't resume on a new instance. This behavior means that the max retry count is a best effort, and in some rare cases an execution could be retried more than the maximum. For Timer triggers, the retries can be less than the maximum requested.

Retry examples

Retries require NuGet package Microsoft.Azure.WebJobs >= 3.0.23

[FunctionName("EventHubTrigger")]
[FixedDelayRetry(5, "00:00:10")]
public static async Task Run([EventHubTrigger("myHub", Connection = "EventHubConnection")] EventData[] events, ILogger log)
{
// ...
}
Property Description
MaxRetryCount Required. The maximum number of retries allowed per function execution. -1 means to retry indefinitely.
DelayInterval The delay that is used between retries. Specify as a string with the format HH:mm:ss.

Here's the retry policy in the function.json file:

{
    "disabled": false,
    "bindings": [
        {
            ....
        }
    ],
    "retry": {
        "strategy": "fixedDelay",
        "maxRetryCount": 4,
        "delayInterval": "00:00:10"
    }
}
function.json property Description
strategy Required. The retry strategy to use. Valid values are fixedDelay or exponentialBackoff.
maxRetryCount Required. The maximum number of retries allowed per function execution. -1 means to retry indefinitely.
delayInterval The delay that is used between retries when using a fixedDelay strategy. Specify as a string with the format HH:mm:ss.
minimumInterval The minimum retry delay when using an exponentialBackoff strategy. Specify as a string with the format HH:mm:ss.
maximumInterval The maximum retry delay when using exponentialBackoff strategy. Specify as a string with the format HH:mm:ss.

Here's a Python sample to use retry context in a function:

import azure.functions
import logging


def main(mytimer: azure.functions.TimerRequest, context: azure.functions.Context) -> None:
    logging.info(f'Current retry count: {context.retry_context.retry_count}')

    if context.retry_context.retry_count == context.retry_context.max_retry_count:
        logging.warn(
            f"Max retries of {context.retry_context.max_retry_count} for "
            f"function {context.function_name} has been reached")

@FunctionName("TimerTriggerJava1")
@FixedDelayRetry(maxRetryCount = 4, delayInterval = "00:00:10")
public void run(
    @TimerTrigger(name = "timerInfo", schedule = "0 */5 * * * *") String timerInfo,
    final ExecutionContext context
) {
    context.getLogger().info("Java Timer trigger function executed at: " + LocalDateTime.now());
}

Binding error codes

When integrating with Azure services, errors may originate from the APIs of the underlying services. Information relating to binding-specific errors is available in the Exceptions and return codes section of the following articles:

Next steps