Errors¶
Every failure raises a subclass of OneSmsError, so a single except OneSmsError
catches everything the client can throw. Most of the time you catch the specific ones
that need their own handling and let the rest bubble up.
Two kinds of failure¶
Problems fall into two groups: the ones caught before a request leaves your machine, and the ones that come back from the API.
OneSmsValidationError is raised locally, for example when the text is empty or the
recipient list is too long. No request is sent. OneSmsConnectionError is raised when
the network fails and the request could not be retried.
Everything the API rejects raises an OneSmsAPIError. It carries the HTTP
status_code, the API error_code, the message, and the raw payload.
Catch what matters¶
from onesms import (
InsufficientBalanceError,
OneSmsAPIError,
OneSmsConnectionError,
OneSmsValidationError,
RateLimitError,
)
try:
client.send_notification(["994501234567"], "Hello")
except OneSmsValidationError as exc:
print("Bad input:", exc)
except InsufficientBalanceError as exc:
print("Top up:", exc.required, "have:", exc.balance)
except RateLimitError as exc:
print("Slow down, retry after:", exc.retry_after)
except OneSmsConnectionError as exc:
print("Network problem:", exc)
except OneSmsAPIError as exc:
print(exc.status_code, exc.error_code, exc.message)
Order the except clauses from specific to general. Since the specific API errors all
inherit from OneSmsAPIError, that clause has to come last.
The full list¶
| Exception | Raised for |
|---|---|
OneSmsValidationError |
Local checks before a request is sent |
OneSmsConnectionError |
Network failures that could not be retried |
BadRequestError |
400 |
AuthenticationError |
401 |
InsufficientBalanceError |
402, adds required and balance |
PermissionDeniedError |
403 |
NotFoundError |
404 |
ConflictError |
409 |
RateLimitError |
429, adds retry_after |
ServerError |
5xx, adds msm_errno, msm_err_text, hint |
OneSmsAPIError |
Base for any API error |
InsufficientBalanceError, RateLimitError, and ServerError add the extra fields
shown above, so you can read them straight off the exception instead of digging
through the raw payload.