Skip to content

Retries and Error Handling

Recover from transient failures with retry policies and defensive error handling in PowerShell.

Retry Policies

Configure a retry policy per-function in function.json, as a sibling of bindings. It applies to trigger types that support runtime-enforced retries (such as Timer, Event Hubs, and Azure Cosmos DB). The policy re-runs the whole function on an unhandled exception.

function.json:

{
  "bindings": [
    {
      "name": "Timer",
      "type": "timerTrigger",
      "direction": "in",
      "schedule": "0 */5 * * * *"
    }
  ],
  "retry": {
    "strategy": "exponentialBackoff",
    "maxRetryCount": 5,
    "minimumInterval": "00:00:02",
    "maximumInterval": "00:01:00"
  }
}

Use "strategy": "fixedDelay" with a "delayInterval" for a constant wait instead of exponential backoff.

Retry support varies by trigger

Built-in retry policies do not apply to every trigger. HTTP triggers, for example, do not retry. Check the binding documentation and, where the source supports it (Service Bus, Queue), rely on the platform's native delivery-count and dead-letter behavior.

Handling Errors in Code

Wrap fallible work in try/catch and throw to signal failure so the retry policy or platform dead-lettering engages:

param($Message, $TriggerMetadata)

try {
    Invoke-RestMethod -Uri $env:DownstreamApi -Method Post -Body $Message -ErrorAction Stop
}
catch {
    Write-Error "Downstream call failed: $($_.Exception.Message)"
    throw
}

Set -ErrorAction Stop on cmdlets so non-terminating errors become catchable terminating errors.

Idempotency

Because a function may run more than once, make handlers idempotent — use a natural key or a processed-message table so reprocessing the same message is safe.

Poison messages

For Queue and Service Bus triggers, messages that keep failing move to a poison queue or dead-letter subqueue after the max delivery count. Monitor and reprocess these separately.

See Also

Sources