Heuristic:Groq Groq python Error Handling Hierarchy
| Knowledge Sources | |
|---|---|
| Domains | API_Client, Error_Handling |
| Last Updated | 2026-02-15 17:00 GMT |
Overview
Structured exception hierarchy for Groq API errors, enabling granular catch patterns from specific status codes to broad connection failures.
Description
The Groq SDK provides a typed exception hierarchy rooted at GroqError. All API-related errors inherit from APIError, which branches into APIConnectionError (network failures) and APIStatusError (HTTP 4xx/5xx responses). Each HTTP status code has a dedicated exception class (e.g., RateLimitError for 429, AuthenticationError for 401), enabling precise error handling. The body property provides the decoded JSON error response, and __cause__ exposes the underlying transport exception.
Usage
Apply this heuristic when writing error handling code for Groq API calls. Catch specific exceptions for status codes you want to handle differently (e.g., back off on RateLimitError, re-authenticate on AuthenticationError). Use the broad APIError catch as a fallback. Access e.status_code, e.response, and e.body for diagnostics.
The Insight (Rule of Thumb)
- Action: Structure try/except blocks from most-specific to least-specific exception type.
- Catch order:
RateLimitError(429) - Implement backoff or queue delayAuthenticationError(401) - Check/refresh API keyBadRequestError(400) - Fix request parametersAPITimeoutError- Increase timeout or reduce request sizeAPIConnectionError- Check network, retry laterAPIStatusError- Log status_code and body for diagnosticsAPIError- Broadest catch for any API-related error
- Trade-off: Catching too broadly (
Exception) masks bugs. Catching too narrowly may miss related errors. - Error body: Access
e.bodyfor the decoded JSON error message from the API. This isNonefor connection errors. - Null vs missing: Use
response.model_fields_setto distinguishNone(explicitly null in JSON) from absent fields.
Reasoning
Different API errors require different handling strategies. Rate limits need backoff, authentication errors need credential refresh, and bad requests need parameter correction. A flat catch-all prevents implementing these distinct recovery strategies. The hierarchy is designed so that catching a parent class (e.g., APIStatusError) automatically catches all child classes (e.g., RateLimitError, BadRequestError), giving developers flexibility in granularity.
Code Evidence
Exception hierarchy from src/groq/_exceptions.py:21-108:
class GroqError(Exception):
pass
class APIError(GroqError):
message: str
request: httpx.Request
body: object | None
class APIStatusError(APIError):
response: httpx.Response
status_code: int
class APIConnectionError(APIError): ...
class APITimeoutError(APIConnectionError): ...
class BadRequestError(APIStatusError): # 400
status_code: Literal[400] = 400
class AuthenticationError(APIStatusError): # 401
status_code: Literal[401] = 401
class PermissionDeniedError(APIStatusError): # 403
status_code: Literal[403] = 403
class NotFoundError(APIStatusError): # 404
status_code: Literal[404] = 404
class ConflictError(APIStatusError): # 409
status_code: Literal[409] = 409
class UnprocessableEntityError(APIStatusError): # 422
status_code: Literal[422] = 422
class RateLimitError(APIStatusError): # 429
status_code: Literal[429] = 429
class InternalServerError(APIStatusError): # 5xx
pass
Recommended error handling pattern from README.md:173-224:
import groq
client = groq.Groq()
try:
client.chat.completions.create(
messages=[{"role": "user", "content": "Hello"}],
model="llama-3.3-70b-versatile",
)
except groq.APIConnectionError as e:
print("The server could not be reached")
print(e.__cause__) # an underlying Exception, likely raised within httpx.
except groq.RateLimitError as e:
print("A 429 status code was received; we should back off a bit.")
except groq.APIStatusError as e:
print("Another non-200-range status code was received")
print(e.status_code)
print(e.response)