Python V1 · Deprecated
Errors
Errors in the Python V1 binding.The Python V1 errors reference continues the Python V1 overview.
Shape errors — Python TypeError / ValueError
Before any native call, the wrapper checks the shape of the arguments on the Python side and raises an ordinary built-in Python exception when it is wrong:
| Input error (rejected in Python) | Raises |
|---|---|
Non-string predicate | TypeError |
Non-integer arity, including bool | TypeError |
Negative arity, or arity > engine.limits.max_arity | ValueError |
terms is not a sequence, or is itself a str/bytes value | TypeError |
max_arity here is the build profile's global ceiling, not each predicate's
declared arity — the Python check only rejects an impossible arity early. A
shape error almost always means a bug in the calling code, so you normally fix
the call rather than catch these at runtime.
Engine errors — MaelysDatalogError
Once the call is well-shaped, the engine itself can still reject it. That
surfaces as a MaelysDatalogError, a subclass of RuntimeError, carrying
.code (an int), .message and .hint (see Diagnostics).
Domain registration also has specialized subclasses:
DomainAlreadyRegisteredError and DomainRegistryFullError.
Two conditions both raise
.code == ERR_INVALID_FIELD:
- an explicit
Term.symbol_id(id)that is not in this ruleset's symbol table — the id is not a valid field value; - an arity within the build limit that does not match the predicate's declared
arity — predicate lookup matches on
(name, arity)together, so a wrong arity is not a registered predicate.
It can also raise ERR_FORBIDDEN (the predicate is a POLICY_FACT kind) or
ERR_PAYLOAD_TOO_LARGE (fact caps). To act on a specific code, compare .code:
from maelys_datalog import C, MaelysDatalogError
try:
edb.add_fact('owns', [Term.symbol_id(bad_id), Term.symbol_id(doc)])
except MaelysDatalogError as exc:
if exc.code == C.ERR_INVALID_FIELD:
... # unknown symbol id, or a wrong (predicate, arity) pairexc.code holds a maelys_result_t return code — the MAELYS_ERR_* values in
the Error codes table (MAELYS_ERR_INVALID_FIELD is -2).
Compare it against the matching constant from C, a namespace of engine
constants the package exports (from maelys_datalog import C). Note the
asymmetry: the predicate-kind flags have plain top-level names — you import
PRED_EDB directly — but the error codes live only on C, under names with
the MAELYS_ prefix dropped, so it is C.ERR_INVALID_FIELD (there is no
top-level ERR_INVALID_FIELD to import).
Catching both
The two kinds come from different layers and share no common base below
Exception: MaelysDatalogError is a RuntimeError, while TypeError and
ValueError are not. So a single except MaelysDatalogError clause does not
catch a shape error. To guard both at once, give each its own clause:
try:
edb.add_fact(predicate, terms)
except (TypeError, ValueError) as exc:
# caller passed the wrong shape (bad predicate/arity/terms type) —
# normally a bug in your code to fix, not a runtime condition
raise
except MaelysDatalogError as exc:
# the engine rejected a well-shaped call — inspect the code
if exc.code == C.ERR_INVALID_FIELD:
... # unknown symbol id, or a wrong (predicate, arity) pairIn practice the first clause is a guard rail (shape bugs surface loudly during development), and the second is where the real runtime conditions land.