Handling errors¶
If a message arrives incomplete, decode() cannot read it:
from bytespec import DecodeError, ProtoModel
class Message(ProtoModel):
text: str
encoded = Message(text="Hello").encode()
try:
Message.decode(encoded[:-1])
except DecodeError:
print("The message is truncated or does not match the model")
The message is truncated or does not match the model
Catch DecodeError where the application receives and decodes external messages. This error also covers invalid text, unknown enum values, and other data that does not fit the model.
A value does not fit in a field¶
from bytespec import EncodeError
from bytespec.types import UInt8
class Packet(ProtoModel):
number: UInt8
packet = Packet(number=256)
try:
packet.encode()
except EncodeError as error:
print(error)
Packet.number: UInt8Codec (B): cannot encode 256
UInt8 only allows numbers up to 255. The instance was created, but encoding failed. A string too long for the chosen prefix and text that cannot be represented in the selected encoding are handled similarly.
Model annotations define the format but do not fully validate explicitly supplied constructor arguments. Pass values of the appropriate types; do not expect "42" to be converted to a number or a dictionary to a model.
An error in a model declaration¶
Invalid settings are detected when the class is created:
from bytespec import SchemaError
try:
class User(ProtoModel):
email: str | None # an optional field needs field(flag=...)
except SchemaError:
print("Add a flag number for email")
Add a flag number for email
SchemaError also occurs for unsupported annotations, duplicate indices, or invalid length prefixes.
Which exceptions to catch¶
Exception |
Meaning |
|---|---|
|
The declared types or settings cannot be used |
|
The value cannot be encoded in the chosen representation |
|
The message cannot be decoded using this model |
|
The common base class for the three errors above |
All four classes are imported from bytespec. If you handle all library errors in the same way, you can catch BytespecError. See Exceptions for the full hierarchy and the cases that raise each exception.
Python call errors remain ordinary exceptions. For example, Message() without the required text raises TypeError. Errors in custom codec implementations are not automatically wrapped either. Exceptions from __validate__ also propagate unchanged, including when called through decode(); handle the application’s chosen exception type separately (see Validating model values). For header checks and their current limitations, see What is checked in 0.1.0.
A field error message includes the model and field names; for wrapped errors, the original cause is available through error.__cause__. For diagnostics, you can print the full exception, as in the second example. Do not treat its text as a machine-readable protocol: separate field and offset attributes are not provided.
This concludes the basic guide. Continue with Files and multiple messages to work with files or multiple messages, Codecs: custom formats and types for custom types, or Binary / wire format to agree on a binary format with another party.