⚠️ Errors#
Exceptions in pywa are a key mechanism for letting you know what went wrong and why.
They appear in two main ways:
Raised exceptions — when something fails immediately (e.g., invalid parameters).
Returned errors — when the API reports an error asynchronously via a message status update.
Basic Example#
Most exceptions are raised directly when you attempt an invalid action:
import logging
from pywa import WhatsApp, types, errors
wa = WhatsApp(...)
try:
wa.send_message(..., buttons=[
types.Button(title="click 1", callback_data="click"),
types.Button(title="click 2", callback_data="click"), # ⚠️duplicate callback_data
])
except errors.InvalidParameter as e:
logging.error(f"Duplicated `callback_data` in buttons: {e}")
Message Status Errors#
Some errors are not raised immediately but instead appear as part of a MessageStatus update.
For example:
Sending a non-template message outside the 24h conversation window →
ReEngagementMessageSending invalid media (wrong file type, too large, invalid URL, etc.) →
MediaUploadError
These errors surface in the status update rather than raising an exception directly.
That’s why it’s important to always register a handler for failed message statuses:
import logging
from pywa import WhatsApp, types, filters
wa = WhatsApp(...)
@wa.on_message_status(filters.failed)
def handle_failed_message(client: WhatsApp, status: types.MessageStatus):
logging.error("Message failed to send to %s: %s",
status.sender, status.error
)
Handling Specific Errors#
You can also filter and handle specific error types:
1import logging
2from pywa import WhatsApp, filters, errors
3
4wa = WhatsApp(...)
5
6wa.send_message(to="972501234567", text="Hello") # 24h window closed
7wa.send_image( # nonexistent image
8 to="972501234567",
9 image="https://example.com/this-image-does-not-exist.jpg",
10 caption="Not found"
11)
12wa.send_document( # file too large
13 to="972501234567",
14 document="https://example.com/document-size-is-too-big.pdf",
15 filename="big.pdf"
16)
17
18@wa.on_message_status(filters.failed_with(errors.ReEngagementMessage))
19def handle_failed_reengagement(client: WhatsApp, status: types.MessageStatus):
20 logging.error("Message failed to send to %s: %s",
21 status.from_user.wa_id, status.error
22 )
23
24@wa.on_status_message(filters.failed_with(errors.MediaUploadError))
25def handle_failed_sent_media(client: WhatsApp, status: types.MessageStatus):
26 logging.error("Message failed to send to %s: %s",
27 status.from_user.wa_id, status.error
28 )
29 status.reply_text("Sorry, I can't upload this file")
30
31@wa.on_status_message(filters.failed_with(errors.MediaDownloadError))
32def handle_failed_received_media(client: WhatsApp, status: types.MessageStatus):
33 logging.error("Got a media download error from %s: %s",
34 status.from_user.wa_id, status.error
35 )
36 status.reply_text("Sorry, I can't download this file")
Incoming Errors (Unsupported Messages)#
If a user sends an unsupported message type (e.g., poll), you’ll receive a Message with type UNSUPPORTED and an error of UnsupportedMessageType.
from pywa import WhatsApp, types, filters
wa = WhatsApp(...)
@wa.on_message(filters.unsupported)
def handle_unsupported_message(client: WhatsApp, msg: types.Message):
msg.reply_text("Sorry, I don't support this message type yet")
Catching All Exceptions#
Since all exceptions inherit from WhatsAppError, you can catch everything with one block:
1from pywa import WhatsApp, errors
2
3wa = WhatsApp(...)
4
5try:
6 wa.send_message(...)
7except errors.WhatsAppError as e:
8 print(f"Error: {e}")
Base Exception#
- class pywa.errors.WhatsAppError#
Bases:
ExceptionBase dataclass for WhatsApp errors.
- Variables:
code (int) – The error code.
message (str) – The error message.
details (str | None) – The error details (optional).
fbtrace_id (str | None) – The Facebook trace ID (optional).
href (str | None) – The href to the documentation (optional).
raw (dict) – The raw error.
raw_response (httpx.Response | None) – The
httpx.Responseobj that returned the error (optional, only if the error was raised from an API call).subcode (int | None) – The error subcode (optional).
type (str | None) – The error type (optional).
is_transient (bool | None) – Whether the error is transient (optional).
user_title (str | None) – The user-facing title for the error (optional).
user_msg (str | None) – The user-facing message for the error (optional).
Categories of Exceptions#
All exceptions fall into one of these categories:
- Sending Messages Errors
SendMessageErrorMessageUndeliverableReEngagementMessageUnsupportedMessageTypeRecipientNotInAllowedListInvalidParameterMissingRequiredParameterMediaDownloadErrorMediaUploadErrorTemplateParamCountMismatchTemplateParamFormatMismatchTemplateNotExistsTemplateTextTooLongGenericErrorUnknownErrorAccessDeniedServiceUnavailableRecipientCannotBeSenderBusinessPaymentIssueIncorrectCertificateAccountInMaintenanceModeUserIsInExperimentGroupRecipientIdentityKeyMismatch
- Flows Errors
- Authorization Errors
- Rate Limit Errors
- Integrity Errors
- Block Users Errors
- Calling Errors