About riverpod-retry
riverpod-retry describes Riverpod's provider retry behavior and how to customize it. Developers can set retry policies per provider or globally, including stopping retries for selected errors.
Key features
- 01Exponential backoff by default
- 02Custom retry function
- 03Per-provider retry settings
- 04Global retry settings
- 05Disable retries with null
Use cases
- 01Retry a provider after transient failures
- 02Set different policies for individual providers
- 03Apply a shared policy through ProviderScope
- 04Stop retrying for selected errors
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ serverpod/ skills-registry --skill riverpod-retryAfter installing, type/riverpod-retryin Claude Code to confirm it loaded.
Details
From the project READMERiverpod — Automatic retry
Instructions
Riverpod retries providers when their computation throws. Retry can be customized per provider or globally.
Default behavior
By default a provider is retried up to a limit (e.g. 10 times) with exponential backoff (e.g. 200ms to 6.4s). Error and ProviderException are not retried: Error indicates a bug; ProviderException means a dependency failed, so the dependent provider is not retried (the underlying one is).
Custom retry function
A retry function has signature Duration? Function(int retryCount, Object error). Return a Duration for the delay before the next retry, or null to stop.
Duration? myRetry(int retryCount, Object error) {
if (retryCount >= 5) return null;
if (error is ProviderException) return null;
return Duration(milliseconds: 200 * (1 << retryCount));
}
Where to set it
- Per provider: Pass
retry: myRetrywhen defining the provider (or@Riverpod(retry: myRetry)with codegen). - Globally: Pass
retry: myRetryto ProviderScope or ProviderContainer.
// Global
ProviderScope(retry: myRetry, child: MyApp())
// Per provider (manual)
final myProvider = Provider<int>(retry: myRetry, (ref) => 0);
Disabling retry
Return null always:
ProviderScope(retry: (retryCount, error) => null, child: MyApp())
Awaiting async providers with retry
ref.watch(myProvider.future) (or equivalent) keeps waiting until either all retries are exhausted or the provider succeeds. So await ref.watch(myProvider.future) skips intermediate failures and completes when the provider finally succeeds or gives up.