Exceptions¶
Every database failure Ferro raises is catchable by type. The tree is
DBAPI-shaped, rooted at FerroError:
FerroError
├── InterfaceError the database interface was misused
├── OperationalError the database or its environment failed
├── DataError a value could not be decoded or converted
├── IntegrityError a constraint rejected the statement
│ ├── UniqueViolationError
│ ├── ForeignKeyViolationError
│ ├── NotNullViolationError
│ └── CheckViolationError
└── ModelDoesNotExist (also a LookupError)
Catch a duplicate insert without matching driver text:
from ferro import UniqueViolationError
try:
await User(email="[email protected]").save()
except UniqueViolationError as exc:
print(exc.sqlstate) # SQLSTATE "23505" on Postgres, result code "2067" on SQLite
print(exc.constraint) # violated constraint name (Postgres only)
print(exc.driver_message) # original driver text, for logs
ModelDoesNotExist is raised by primary-key lookups like Model.get(pk) when
no row matches — use Model.get_or_none(pk) if you prefer None over an
exception — and by save() on a persisted instance whose row no longer exists
(see Saving: INSERT or UPDATE).
It remains a LookupError, so pre-existing except LookupError handlers keep
working.
FerroError
¶
Bases: Exception
Root of Ferro's database exception hierarchy.
Attributes:
| Name | Type | Description |
|---|---|---|
driver_message |
str | None
|
Original message from the database driver, when the
error originated in the database. |
sqlstate |
str | None
|
Backend error code as reported by the driver: the
five-character SQLSTATE (e.g. |
constraint |
str | None
|
Name of the violated constraint when the backend reports
it (Postgres does; SQLite does not). |
Source code in src/ferro/exceptions.py
InterfaceError
¶
Bases: FerroError
The database interface was misused.
Raised for problems on the client side of the conversation: operating on an unknown or uninitialized connection name, driver protocol errors, or invalid connection configuration.
Source code in src/ferro/exceptions.py
OperationalError
¶
Bases: FerroError
The database or its environment failed.
Raised for failures outside the program's control: the server is unreachable, a connection pool timed out or is closed, or an I/O or TLS error interrupted the conversation.
Source code in src/ferro/exceptions.py
DataError
¶
Bases: FerroError
A value could not be decoded or converted.
Raised when a fetched value cannot be decoded into the expected Python type or a bound value cannot be represented for the column type.
Source code in src/ferro/exceptions.py
IntegrityError
¶
Bases: FerroError
A database constraint rejected the statement.
Source code in src/ferro/exceptions.py
UniqueViolationError
¶
Bases: IntegrityError
A UNIQUE or PRIMARY KEY constraint rejected the statement.
Source code in src/ferro/exceptions.py
ForeignKeyViolationError
¶
Bases: IntegrityError
A FOREIGN KEY constraint rejected the statement.
Source code in src/ferro/exceptions.py
NotNullViolationError
¶
Bases: IntegrityError
A NOT NULL constraint rejected the statement.
Source code in src/ferro/exceptions.py
CheckViolationError
¶
Bases: IntegrityError
A CHECK constraint rejected the statement.
Source code in src/ferro/exceptions.py
ModelDoesNotExist
¶
Bases: FerroError, LookupError
Raised when :meth:~ferro.models.Model.get finds no row for the primary
key, and when :meth:~ferro.models.Model.save on a persisted instance
matches no row (the row was deleted underneath, or the primary key was
mutated before saving).