Skip to content

Errors

The Dart SDK's sealed exception types, retries and rate limits.

Every failure is a VaultbaseException. It’s a sealed class, so a switch over it is checked for every case:

try {
await vb.collection('posts').create({'title': ''});
} on VaultbaseException catch (e) {
final text = switch (e) {
ValidationException(:final details) => details.values.join('\n'),
AuthException(reason: AuthFailure.forbidden) => "You can't do that.",
AuthException() => 'Please sign in again.',
RateLimitException(:final retryAfter) => 'Slow down: retry in ${retryAfter.inSeconds}s.',
MaintenanceException(:final message) => message,
PreconditionFailedException() => 'Someone else changed this; reload.',
ConflictException() => 'That already exists.',
NetworkException() => 'No connection.',
CancelledException() => '',
ServerException(:final status) => 'Server error ($status).',
};
}
ExceptionWhen
NetworkExceptionNo response: offline, DNS, timeout (cause has the underlying error)
AuthException401 / 403. reason is expired, invalid or forbidden
ValidationException422. details maps field names to messages
RateLimitException429. retryAfter from the server, at most 10 s
MaintenanceException503 from a server in maintenance mode. level is full or readOnly; until and retryAfter when the admin set a time
ConflictException409, e.g. a unique value taken
PreconditionFailedException412: the record changed since you read it (see ETags); currentEtag when the server sends it
CancelledExceptionA CancelToken, a newer request with the same key, or a closed sign-in browser
ServerExceptionAnything else, with status and body

Every exception keeps message, status, the server’s error code, and the response body.

A 401 on a request triggers one token refresh and one retry. If the retry is refused too, the exception’s reason is forbidden and the session is kept: the token is fine, the rules said no.