AI Exceptions
When to Use
Use this guide when handling errors from AI provider calls. Always catch specific exceptions before the generic
AiExceptionInterface.
All AI exceptions implement AiExceptionInterface (extends \Throwable). Catch this interface to handle any AI-specific error generically.
Decision
| Situation | Choose | Why |
|---|---|---|
| Handle all AI errors generically | AiExceptionInterface |
All AI exceptions implement this |
| Rate limit with backoff | AiRateLimitException |
Provider hit rate limit |
| Out of credits | AiQuotaException |
Provider quota exhausted |
| Content blocked | AiUnsafePromptException |
Guardrail or moderation blocked |
| Bad API key / setup | AiSetupFailureException |
Known broken setup |
| Provider doesn't support feature | AiMissingFeatureException |
e.g., streaming on non-streaming provider |
| Graceful failover on any error | AiExceptionEvent subscriber (1.4) |
Inject cached/fallback response before re-throw |
Pattern
use Drupal\ai\Exception\AiExceptionInterface;
use Drupal\ai\Exception\AiRateLimitException;
use Drupal\ai\Exception\AiUnsafePromptException;
try {
$output = $provider->chat($input, $model, ['my_module']);
} catch (AiRateLimitException $e) {
// Retry with exponential backoff.
} catch (AiUnsafePromptException $e) {
// Content was blocked by moderation/guardrails.
$this->messenger->addError($this->t('Request blocked.'));
} catch (AiExceptionInterface $e) {
// Generic AI error handling.
$this->logger->error('AI error: @msg', ['@msg' => $e->getMessage()]);
}
Exception Reference
| Exception | When Thrown |
|---|---|
AiBadRequestException |
Malformed request, missing model ID, client invocation error, or unclassified provider error |
AiRateLimitException |
Provider reports rate limiting |
AiQuotaException |
Provider reports exhausted credits/quota |
AiAccessDeniedException |
Provider denies access even though setup is correct (e.g., model-level restriction) |
AiRequestErrorException |
Request structure error or generic request failure |
AiResponseErrorException |
Unexpected or malformed provider response |
AiSetupFailureException |
Known provider setup is broken (bad API key, misconfigured endpoint) |
AiMissingFeatureException |
Requested feature not supported by provider (e.g., streaming on non-streaming provider) |
AiUnsafePromptException |
Content moderation or guardrail blocked the prompt |
AiBrokenOutputException |
Input or output corrupted by manipulation (e.g., guardrail rewrite produced invalid data) |
AiOperationTypeMissingException |
Called an operation type the provider doesn't implement |
AiToolsValidationException |
Tool/function call validation failed |
AiFunctionCallingExecutionError |
Error during tool/function execution |
ChunkingTooSmallException |
Text chunk smaller than minimum constraints (embedding strategy) |
ProviderProxy Exception Handling
The ProviderProxy catches exceptions from provider calls and re-throws them with logging. Specific types (AiResponseErrorException, AiMissingFeatureException, AiQuotaException, AiRateLimitException, AiUnsafePromptException, AiRequestErrorException) are re-thrown as-is. ClientExceptionInterface (PSR HTTP) is wrapped in AiBadRequestException. Any other \Exception is wrapped in AiRequestErrorException.
Changed in 1.4: Before re-throwing, the proxy dispatches AiExceptionEvent. Subscribers can inject a forced recovery output via setForcedOutputObject() — the proxy uses this instead of re-throwing. See Events System.
Common Mistakes
- Wrong: Catching only
\Exception→ Right: CatchAiExceptionInterfaceto specifically handle AI errors - Wrong: Not catching
AiUnsafePromptExceptionin user-facing features → Right: This exception is thrown when guardrails block content; handle gracefully - Wrong: Not using
AiExceptionEventfor rate limit fallback (1.4) → Right: Subscribe toAiExceptionEventto inject cached responses when providers fail
See Also
- Guardrails System
- Events System
- Reference:
web/modules/contrib/ai/src/Exception/