Error Handling
In case of erroneous transactions, connection problems and a lot of other cases, PyLinkAhead may raise specific errors in order to pinpoint the problem as precisely as possible. Some of these errors a representations of errors in the LinkAhead server, others stem from problems that occurred on the client side.
The errors and exceptions are ordered hierarchically form the most general exceptions to specific transaction or connection problems. The most important error types and the hierarchy will be explained in the following. For more information on specific error types, see also the source code.
Note
Starting from PyCaosDB 0.5, the error handling has changed
significantly. New error classes have been introduced and the
behavior of TransactionError
and EntityError
has been
re-worked. In the following, only the “new” errors are
discussed. Please refer to the documentation of PyCaosDB 0.4.1 and
earlier for the old error handling.
LinkAheadException
LinkAheadException
is the most generic exception and all other error classes inherit
from this one. Because of its generality, it doesn’t tell you much
except that some component of PyLinkAhead raised an exception. If you
want to catch all possible LinkAhead errors, this is the class to use.
TransactionError
Every transaction (calling insert
, update
, retrieve
, or
delete
on a container or an entity) may finish with errors. They
indicate, for instance, that an entity does not exist or that you need
to specify a data type for your property and much more. If and only if
one or more errors occur during a transaction a TransactionError
will be raised by the transaction method. The TransactionError
class is a container for all errors which occur during a
transaction. It usually contains one or more entity
errors which you can inspect in order to learn why the
transaction failed. For this inspection, there are some helpful
attributes and methods provided by the TransactionError
:
entities
: a list of all entities that directly caused at least one error in this transaction.errors
: a list of allEntityError
objects that directly caused the transaction to fail.all_entities
,all_errors
: sets of all entities and errors that, directly or indirectly, caused either thisTransactionError
or any of theEntityError
objects it contains.has_error(error_t)
: Check whether an error of typeerror_t
occurred during the transaction.
Additionally, print(transaction_error)
prints a tree-like
representation of all errors regarding the transaction in question.
EntityError
An EntityError
specifies the entity and the error proper that
caused a transaction to fail. It is never raised on its own but is
contained in a TransactionError
(which may or may not contain
other EntityError
objects) which is then raised. EntityError
has several subclasses that further specify the
error that occurred.
The EntityError
class is in fact a subclass of
TransactionError
. Thus, it has the same methods and attributes as
the TransactionError
explained
above. This is important in case of an
EntityError
that was caused by other faulty entities (e.g., broken
parents or properties). In that case these problematic entities and
errors can again be inspected by visiting the entities
and
errors
lists as above.
Special Errors
Subclasses of EntityError
for special purposes:
EntityDoesNotExistError
EntityHasNoDataTypeError
UniqueNamesError
UnqualifiedParentsError
UnqualifiedPropertiesError
ConsistencyError
AuthorizationError
AmbiguousEntityError
BadQueryError
A BadQueryError
is raised when a query could not be processed by
the server. In contrast to a TransactionError
it is not
necessarily caused by problematic entities or
containers. BadQueryError
has the two important subclasses
EmptyUniqueQueryError
and QueryNotUniqueError
for queries with
unique=True
which found no or ambiguous entities, respectively.
HTTP Errors
An HTTPClientError
or an HTTPServerError
is raised in case of
http(s) connection problems caused by the Python client or the LinkAhead
server, respectively. There are the following subclasses of
HTTPClientError
that are used to specify the connection problem:
HTTPURITooLongError
: The URI of the request was too long to be processed by the server.HTTPForbiddenError
: You’re not allowed to access this resource.HTTPResourceNotFoundError
: The requested resource doesn’t exist.
Other Errors
There are further subclasses of LinkAheadException
that are raised in
case of faulty configurations or other problems. They should be rather
self-explanatory from their names; see the source code
for further information.
ConfigurationError
LoginFailedError
MismatchingEntitiesError
ServerConfigurationException
Examples
import linkahead as db
def link_and_insert(entity, linked, link=True):
"""Link the ENTITY to LINKED and insert it."""
if link:
entity.add_property(db.Property(name="link", value=linked))
try:
entity.insert()
except db.TransactionError as tre:
# Unique names problem may be worked around by using another name
if tre.has_error(db.UniqueNamesError):
for ent_error in tre.errors:
if (isinstance(ent_error, db.UniqueNamesError)
and entity in ent_error.entities):
entity.name = entity.name + "_new" # Try again with new name.
link_and_insert(entity, linked, link=False)
break
# Unqualified properties will be handled by the caller
elif tre.has_error(db.UnqualifiedPropertiesError):
for ent_error in tre.errors:
if (isinstance(ent_error, db.UnqualifiedPropertiesError_
and entity in ent_error.entities):
raise RuntimeError("One of the properties was unqualified: " + str(ent_error))
# Other problems are not covered by this tutorial
else:
raise NotImplementedError("Unhandled TransactionError: " + str(tre))