Python
Errors
Errors in the unified Python binding.The Python errors reference continues the Python overview.
Exception and value classes
| Class | Kind | Role |
|---|---|---|
MaelysDatalogError | Exception class | Exception carrying a native status and structured diagnostic. |
Diagnostic | Immutable value class | Immutable native detail record, separate from the operation status. |
Status | Enumeration | Named native operation statuses, used when handling exceptions. |
Properties and attributes
Read properties without parentheses. Their links lead to the class card defined on this page.
| Property / protocol | Type | Meaning |
|---|---|---|
error.status | int | Native operation status; compare with Status members. |
error.code | int | Alias of error.status; not the diagnostic reason code. |
error.message | str | Human-readable detail. |
error.hint | str | Suggested corrective action when supplied. |
error.diagnostic | Diagnostic | Structured native detail, including its distinct reason code and presence mask. |
Detailed API reference
Every class and method indexed at the start of this page has its detailed card here. A class’s method list also links to related operations documented on other topic pages; those links do not duplicate their cards.
Value-class declarations and public creation signatures below come from the published binding inventory. Resource-owning classes list their methods as individual links with a short explanation. Each link opens the complete signature, arguments, return behavior and example; the creation signatures are a reference, not executable class source. The examples are fragments: engine, ruleset, edb, session and result refer to the live objects explained on this page and in the complete examples. Import the named classes before using them.
MaelysDatalogError reference
MaelysDatalogError(
code: int,
message: str,
hint: str = '',
*,
diagnostic: Diagnostic | None = None,
) -> MaelysDatalogErrorfrom maelys_datalog import MaelysDatalogError, Status
try:
edb.add_fact("owns", ["alice", "roadmap.pdf"])
result = session.solve(edb)
except MaelysDatalogError as error:
print(Status(error.status).name)
print(error.message, error.hint)Receiving a MaelysDatalogError
A failed native operation raises this exception. Application code normally catches it rather than constructs it; malformed Python arguments may instead raise TypeError, ValueError or OverflowError.
MaelysDatalogError attributes
Read these attributes without parentheses; they are not callable methods.
| Attribute / protocol | Type | Meaning |
|---|---|---|
error.status | int | Native operation status; compare with Status members. |
error.code | int | Alias of error.status; not the diagnostic reason code. |
error.message | str | Human-readable detail. |
error.hint | str | Suggested corrective action when supplied. |
error.diagnostic | Diagnostic | Structured native detail, including its distinct reason code and presence mask. |
Diagnostic reference
@dataclass(frozen=True)
class Diagnostic:
source: int = 0
status: int = 0
code: int = 0
present: int = 0
line: int = 0
column: int = 0
phase: str = ''
message: str = ''
hint: str = ''
file: str = ''
predicate: str = ''
arity: int = 0
observed_count: int = 0
limit: int = 0
depth: int = 0
depth_limit: int = 0
rule_id: int = 0
comparison_result: int = 0
expected_kind: int = 0
lhs_kind: int = 0
rhs_kind: int = 0
comparison_op: int = 0
limit_kind: int = 0
term_index: int = 0
expected_arity: int = 0
observed_arity: int = 0
token: str = ''
field: str = ''
domain: str = ''try:
ruleset = engine.load_manifest("policies/manifest.json")
except MaelysDatalogError as error:
detail = error.diagnostic
print(detail.phase, detail.message, detail.hint)
print(detail.file, detail.line, detail.column)Status reference
class Status(IntEnum):
OK = int(lib.MAELYS_DATALOG_STATUS_OK)
INVALID_ARGUMENT = int(lib.MAELYS_DATALOG_STATUS_INVALID_ARGUMENT)
INVALID_FIELD = int(lib.MAELYS_DATALOG_STATUS_INVALID_FIELD)
NOT_FOUND = int(lib.MAELYS_DATALOG_STATUS_NOT_FOUND)
NOT_IMPLEMENTED = int(lib.MAELYS_DATALOG_STATUS_NOT_IMPLEMENTED)
UNSUPPORTED = int(lib.MAELYS_DATALOG_STATUS_UNSUPPORTED)
TIMEOUT = int(lib.MAELYS_DATALOG_STATUS_TIMEOUT)
IO = int(lib.MAELYS_DATALOG_STATUS_IO)
INTERNAL = int(lib.MAELYS_DATALOG_STATUS_INTERNAL)
UNAUTHORIZED = int(lib.MAELYS_DATALOG_STATUS_UNAUTHORIZED)
FORBIDDEN = int(lib.MAELYS_DATALOG_STATUS_FORBIDDEN)
RATE_LIMITED = int(lib.MAELYS_DATALOG_STATUS_RATE_LIMITED)
PAYLOAD_TOO_LARGE = int(lib.MAELYS_DATALOG_STATUS_PAYLOAD_TOO_LARGE)
INVALID_STATE = int(lib.MAELYS_DATALOG_STATUS_INVALID_STATE)
STORAGE_TOO_SMALL = int(lib.MAELYS_DATALOG_STATUS_STORAGE_TOO_SMALL)from maelys_datalog import Status
if error.status == Status.UNSUPPORTED:
print("The requested native feature is unsupported")Usage and examples
Distinguish Python argument errors from native engine failures, then place both addition and solving inside an appropriate exception handler.
The reference above gives the exact declarations; the sections below explain their use.
Python exceptions
The following built-in exceptions are not additional binding classes. Their links explain the rejected input or lifecycle operation.
| Exception | Meaning |
|---|---|
TypeError | Wrong Python representation. |
ValueError | Invalid value or embedded NUL. |
OverflowError | Integer outside signed 64-bit range. |
RuntimeError | Lifecycle misuse; also the superclass of MaelysDatalogError. |
Shape errors and native errors
An input can fail in two very different ways, from two different layers: a wrongly shaped Python call, or a well-shaped fact that the engine rejects. They raise different exception types, and they occur at different times in Python.
Shape errors — Python exceptions
Before buffering a fact, the wrapper checks its Python representation. It also validates query and enumeration arguments before passing them to C:
| Input error | Where checked | Raises |
|---|---|---|
| Predicate name is not a nonempty string | Addition/query/enumeration | TypeError |
terms is not a sequence, or is itself str/bytes | Addition/query | TypeError |
Unsupported term such as float or a legacy Term | Addition/query | TypeError |
| Embedded NUL in a name or symbol string | Addition/query | ValueError |
| Integer outside signed 64-bit range | Addition/query | OverflowError |
| Too many terms for the public facade | Addition/query | ValueError |
Enumeration arity is not an integer, or is bool | Enumeration | TypeError |
| Enumeration arity is negative or exceeds the facade ceiling | Enumeration | ValueError |
The facade ceiling is not a declaration of each predicate's arity. A
three-term owns fact can pass the Python shape check even if the domain
declares owns/2. Exact vocabulary validation happens in the engine.
Shape errors normally mean a caller bug: fix the call rather than treating
them as a negative policy decision.
Engine errors — MaelysDatalogError
Native storage errors can now occur at addition: the total entry limit, individual text byte bounds and allocation failures. Unknown predicates, wrong declared arity, forbidden predicate kinds, symbol-pool and per-predicate limits remain solve-time checks. The buffer is independent of a selected policy. Keep the exception handler around both addition and solve.
MaelysDatalogError is a subclass of RuntimeError. Its .status and .code
carry the facade's operation status; .message and .hint explain it.
The full .diagnostic is separate. Do not import the old binding's C error
namespace or assume its specialized registration exception classes exist here.
See Diagnostics for the distinction between status and
diagnostic code.
Catching both
The exceptions come from different layers: MaelysDatalogError is a
RuntimeError, while TypeError, ValueError and OverflowError are not.
An except MaelysDatalogError clause therefore does not catch a malformed
Python call. Keep both addition and solve inside the protected block:
try:
edb.add_fact(predicate, terms) # Python shape + native storage validation.
result = ruleset.solve(edb) # Native vocabulary/capacity validation.
except (TypeError, ValueError, OverflowError):
raise # Fix the caller's representation.
except MaelysDatalogError as exc:
print(exc.status, exc.message, exc.hint)
raise # Never turn an engine failure into ALLOW.In practice the first clause is a development guard rail, while the second
is where native runtime conditions land. A wrong owner thread or use after
close is a separate lifecycle RuntimeError, not a policy decision.