Error Handling
Every failed request raises a typed exception. All of them inherit from
StronglyError, so you can catch broadly or narrowly. Import them from the
top-level package:
from strongly import (
StronglyError, # base class for everything below
APIError, # base for any HTTP error response
AuthenticationError, # 401 - bad or missing API key
PermissionDeniedError,# 403 - key lacks the required scope
NotFoundError, # 404 - resource does not exist
ConflictError, # 409 - state conflict
PayloadTooLargeError, # 413
UnsupportedMediaTypeError, # 415
UnprocessableEntityError, # 422
ValidationError, # 400 - invalid request body / params
RateLimitError, # 429 - honors Retry-After
InternalServerError, # 500
BadGatewayError, # 502
ServiceUnavailableError, # 503
RequestTimeoutError, # 408
TimeoutError, # client-side request timeout
ConnectionError, # client-side connection failure
ConfigurationError, # misconfiguration (e.g. no API key resolved)
)
Catching errors
from strongly import Strongly, NotFoundError, RateLimitError, APIError
client = Strongly()
try:
workflow = client.workflows.retrieve("wf-123")
except NotFoundError:
print("That workflow does not exist")
except RateLimitError as exc:
print("Rate limited; retry later:", exc)
except APIError as exc:
# Any other HTTP error (status >= 400)
print(f"API error {exc.status_code}: {exc}")
What an APIError carries
APIError (and its subclasses) expose the HTTP status code and the server's
error payload:
try:
client.apps.deploy("app-1")
except APIError as exc:
print(exc.status_code) # e.g. 409
print(str(exc)) # human-readable message from the platform
print(exc.request_id) # X-Request-Id for support / tracing
Retries
The client automatically retries transient failures (timeouts, connection
errors, 429, and 5xx) with exponential backoff and full jitter, honoring the
Retry-After header on 429. Tune it with max_retries:
client = Strongly(max_retries=5) # default is 3
Errors that are not retryable (4xx other than 429) raise immediately.
Deletes raise, not return
Every delete() returns None and raises on failure (it does not return a
status object). Confirm a delete by catching the absence on a subsequent read:
client.memory.delete(memory_id) # -> None
client.memory.retrieve(memory_id) # raises NotFoundError