Error types
Every Rust-level error is a variant of a single enum,XlogError (defined in
crates/xlog-core/src/error.rs). The enum is marked non-exhaustive, so new
variants may be added without a breaking change.
Exit codes
Thexlog CLI returns 0 on success and 1 on any error. Every failure — parse,
compile, execution, I/O, or an exhausted memory budget — surfaces as exit code 1
with a descriptive message on stderr. There are no other exit codes.
Fail-closed rejections you may hit
Module import rejection
Module resolution completes before deterministic or probabilistic compilation. It reports these typed diagnostics rather than compiling a program with missing imported behavior:
The entry file is loaded from the exact path supplied to the CLI. Imported module paths
continue to resolve to
.xlog files. Queries and probabilistic queries in imported
modules are entry-file-scoped and are not merged; imported pragmas are ignored with
warning[W0510]. See Modules for examples and visibility
rules.
Function expansion rejection
User-defined functions expand after module resolution. Production compilation registers function declarations in source order, then expands only definitions reachable from calls in ordinary rules and constraints. An unused definition whose body is recursive, calls an undefined function, or shares a name with a predicate does not block that demand-driven path. Rust callers can instead request strict whole-program validation withFunctionRegistry::from_program. That surface inspects every definition in declaration
order and every callee in source order, including definitions that production expansion
would not reach.
E0506 and E0507 are unassigned.
Strict validation accepts a recursive SCC when at least one member has a conditional
body. That is a structural validation result, not a runtime termination guarantee:
function normalization expands both branches eagerly, and a used cycle can still reach
E0504 at the configured depth.
Cross-predicate type mismatch
Compilation rejects a rule whose variables draw incompatible column types from the declared schemas of the predicates they touch. The conflict may be between two body atoms, or between a body atom and the head. Both forms areCompilation errors that name the rule, the variable, both types, and where each
came from:
pred declaration;
an undeclared predicate has no schema to contradict. Available since 0.12.0 —
before that the same program was accepted here and failed later with an internal
GPU schema error that did not name the rule.
Epistemic rejections
UnsupportedEpistemicConstruct is one error type covering many distinct
rejections. The construct field in the message tells you which one you hit;
find it in the left column below. (A modal literal is one written with know
or possible. A world view is the set of models the program considers possible
at once. A tuple key is the argument list that identifies which tuple a modal
literal is talking about.)
g91 and faeel are the two epistemic semantics you pick between with
#pragma epistemic_mode; faeel is the default. See
Epistemic support and boundaries
for the same boundaries stated as language rules, and
Epistemic reasoning for what the two modes mean.
Resident Monte Carlo rejection
The production Monte Carlo engine — which estimates probabilities by sampling many random possible worlds — runs entirely on the GPU (“resident”) within fixed memory bounds. At compile time it checks every rule and fact against the model of what the device can run; anything outside that model is rejected with a typedResidentRejection (surfaced as a Compilation error of the form
resident MC engine rejected program [kind=...] construct=... context=...).
There is no silent CPU fallback.
On the CLI,
xlog prob --allow-cpu-oracle lets a rejected program run on a labeled
CPU oracle instead; the result is tagged mc_engine: "cpu-oracle" and is never
GPU-native evidence. Without the flag, a rejected program fails. See the
CLI reference.Exact aggregate caps
The exact engine (exact_ddnnf) computes probabilities exactly rather than by
sampling. It evaluates aggregates over finite probabilistic domains using
dynamic programming, and that evaluation is capped per aggregate group:
- Count-only aggregates: at most 64 uncertain rows per group.
- All other aggregates (
sum,min,max,logsumexp): at most 16 uncertain rows per group.
Compilation error that names the predicate, the group key,
and the cap, and tells you the way out: use prob_engine = mc or reduce the finite aggregate domain. The Monte Carlo engine has no such cap because it samples
worlds instead of enumerating outcome formulas. See
Probabilistic engines for choosing between the two.
Multiway union size caps
The GPU sort and dedup steps that merge same-head rule outputs index column bytes with 32-bit arithmetic, so they reject any column whose logical bytes exceed4294967295 (u32::MAX) with a typed error of the form
Sort supports at most 4294967295 bytes per column, got ... (column N); the
concatenation step applies analogous byte caps, Concat: total_bytes too large: ...
and Concat: col_bytes too large: .... Since 0.12.0 the clauses of one head merge
in a single batched concat pass, and that pass additionally rejects more than
4294967295 total rows with Concat supports at most 4294967295 rows, got ....
These are all fail-closed declines, never silent truncation: a relation column
past 4 GiB stops the run instead of scattering rows.
Compile and verify budgets
These two budgets let the engine refuse an oversized problem cleanly instead of crashing the GPU. Available since 0.10.0, the knowledge-compilation phase (D4) and verify-phase controls decline oversized instances rather than risk a CUDA launch failure that would leave the GPU unusable for the rest of the process:- A CNF (Boolean formula in conjunctive normal form) whose variable or clause
capacity exceeds
XLOG_D4_VERIFY_MAX_VARS/XLOG_D4_VERIFY_MAX_CLAUSESdeclines before any kernel launch withCompileCapacityExceeded. Both bounds default to unbounded. - A verify whose SAT search exhausts
XLOG_D4_VERIFY_MAX_CONFLICTSdeclines withVerifyBudgetExceeded— an indeterminate search result is never reported as a proof. The default budget of0means unlimited.
mc engine. See
Environment variables for the knobs.
Python exceptions
pyxlog maps the Rust error surface onto standard Python exception types:
In a source-only import without
pyxlog._native, package-level
RelationMetadataError and RelationEvidence remain importable. The fallback
metadata error still subclasses ValueError; only native evidence instances and
session operations require the extension.
See also
- CLI reference — subcommands, flags, and the exit-code contract
- Probabilistic engines — when to use
exact_ddnnfvsmc - Environment variables — budgets and kill switches