C Stable API

Errors

Interpret stable C status values and public diagnostics fail-closed.

The C facade returns maelys_datalog_status_t from its public calls. Use these status names from <maelys/datalog.h> when handling a failure. A diagnostic can add source context; it does not turn a failed operation into a result.

Types

Defined on this page

TypePurpose
maelys_datalog_status_tMachine-readable outcome of a public call.
maelys_datalog_diagnostic_tOptional source location, reason and typed details for a failed call.

Functions

FunctionPurpose
maelys_datalog_status_name()Print a public status for diagnostics.
maelys_datalog_diagnostic_initializer()Make a correctly initialized diagnostic value.
maelys_datalog_diagnostic_init()Initialize caller-owned diagnostic storage.
maelys_datalog_diagnostic_clear()Reuse a diagnostic after a call.
maelys_datalog_diag_code_name()Print a typed diagnostic reason.

Status type

C · enum
maelys_datalog_status_t
typedef enum {
    MAELYS_DATALOG_STATUS_OK = 0,
    MAELYS_DATALOG_STATUS_INVALID_ARGUMENT = -1,
    MAELYS_DATALOG_STATUS_INVALID_FIELD = -2,
    MAELYS_DATALOG_STATUS_NOT_FOUND = -3,
    MAELYS_DATALOG_STATUS_NOT_IMPLEMENTED = -4,
    MAELYS_DATALOG_STATUS_UNSUPPORTED = -5,
    MAELYS_DATALOG_STATUS_TIMEOUT = -6,
    MAELYS_DATALOG_STATUS_IO = -7,
    MAELYS_DATALOG_STATUS_INTERNAL = -8,
    MAELYS_DATALOG_STATUS_UNAUTHORIZED = -9,
    MAELYS_DATALOG_STATUS_FORBIDDEN = -10,
    MAELYS_DATALOG_STATUS_RATE_LIMITED = -11,
    MAELYS_DATALOG_STATUS_PAYLOAD_TOO_LARGE = -12,
    MAELYS_DATALOG_STATUS_INVALID_STATE = -13,
    MAELYS_DATALOG_STATUS_STORAGE_TOO_SMALL = -14
} maelys_datalog_status_t;
Machine-readable outcome of a public call. OK is success; other values must never be treated as a negative membership answer.

Public diagnostics

Ask for a diagnostic when a loading, input or solve failure needs more detail than its status. Check the present mask before reading an optional section.

C · structSince v0.10.0
maelys_datalog_diagnostic_t
typedef struct {
    size_t struct_size;
    uint32_t abi_version;
    maelys_datalog_diagnostic_source_t source;
    maelys_datalog_status_t status;
    maelys_datalog_diag_code_t code;
    uint64_t present;
    size_t line, column;
    char phase[32], message[256], hint[256];
    char file[256], predicate[96];
    size_t arity, observed_count, limit, depth, depth_limit, rule_id;
    unsigned comparison_result, expected_kind, lhs_kind, rhs_kind, comparison_op;
    maelys_datalog_limit_t limit_kind; /* 0 when the producer cannot identify the budget. */
    size_t term_index, expected_arity, observed_arity;
    char token[96], field[96], domain[96];
} maelys_datalog_diagnostic_t;
Versioned diagnostic record: owned text plus independent typed detail sections. Initialize before every producer call.
Fields
struct_sizesize_t
Size of the caller-provided object in bytes; required by diagnostic ABI 1.
abi_versionuint32_t
Set to MAELYS_DATALOG_DIAGNOSTIC_ABI_VERSION (1).
sourcemaelys_datalog_diagnostic_source_t
LOAD, SOLVE or NONE; NONE means no detail was supplied.
statusmaelys_datalog_status_t
Status associated with this populated diagnostic.
codemaelys_datalog_diag_code_t
Typed reason; use maelys_datalog_diag_code_name() for its stable name.
presentuint64_t
Bitmask selecting the independent detail sections that are valid.
linesize_t
Source line when LOCATION is present.
columnsize_t
Source column when LOCATION is present.
phasechar[32]
Bounded producer phase text.
messagechar[256]
Bounded human-readable message, not a machine-readable code.
hintchar[256]
Bounded optional corrective guidance.
filechar[256]
Bounded source path when LOCATION is present.
predicatechar[96]
Predicate name when PREDICATE is present.
aritysize_t
Predicate arity when PREDICATE is present.
observed_countsize_t
Attempted count for a CAPACITY failure.
limitsize_t
Capacity bound, or inclusive numeric aggregate bound when AGGREGATE is present.
depthsize_t
Observed depth when DEPTH is present.
depth_limitsize_t
Allowed depth when DEPTH is present.
rule_idsize_t
Rule identifier when RULE is present.
comparison_resultunsigned int
Comparison outcome when COMPARISON is present.
expected_kindunsigned int
Expected comparison kind when COMPARISON is present.
lhs_kindunsigned int
Left-hand IR kind; also the offending aggregate value kind.
rhs_kindunsigned int
Right-hand IR kind when COMPARISON is present.
comparison_opunsigned int
IR comparison operator when COMPARISON is present.
limit_kindmaelys_datalog_limit_t
Public capacity identifier; zero when no budget identity is available.
term_indexsize_t
Zero-based term or aggregate projection index when its section is present.
expected_aritysize_t
Required arity when ARITY is present.
observed_aritysize_t
Supplied arity when ARITY is present.
tokenchar[96]
Bounded offending token or aggregate value text.
fieldchar[96]
Bounded field name; min, max or sum for aggregate rejection.
domainchar[96]
Bounded domain name when CONTEXT is present.

The caller owns this record. Initialize it before passing it to a loader, an input insertion or a solve. Diagnostic ABI 1 requires the complete, naturally aligned object: use sizeof(maelys_datalog_diagnostic_t), not a hard-coded byte count. It measures 1328 bytes on the verified macOS arm64 build, but its size is a property of the installed header and target ABI.

Public status values

C · function
Name a public status
const char *
maelys_datalog_status_name(
maelys_datalog_status_t status
);
Converts a public status code into a readable name for logs and error messages.
Arguments
statusmaelys_datalog_status_t
Status returned by a public API call.
Return value
const char *

Returns a readable status name for diagnostics; do not infer success from the text alone.

CODE
const char *name = maelys_datalog_status_name(status);

All values below belong to maelys_datalog_status_t in the installed <maelys/datalog.h> header. The table abbreviates the common MAELYS_DATALOG_STATUS_ prefix. A particular operation may return only a subset; its own contract remains the authority for that call.

SuffixValueMeaning
OK0Operation succeeded; for a query, inspect out_present separately.
INVALID_ARGUMENT-1Required argument or call shape is invalid.
INVALID_FIELD-2Input content violates a field or policy constraint.
NOT_FOUND-3A required item, policy, or query symbol is absent.
NOT_IMPLEMENTED-4The requested operation is recognized but not implemented.
UNSUPPORTED-5A capability, backend feature, or limit key is unavailable.
TIMEOUT-6A bounded operation exceeded its allowance.
IO-7File or other I/O failed.
INTERNAL-8The engine encountered an internal failure.
UNAUTHORIZED-9The caller is not authorized for an operation that requires it.
FORBIDDEN-10A guarded action was refused, for example loading an enabled test-only policy without permission.
RATE_LIMITED-11A provider or bounded service rejected an operation due to rate limiting.
PAYLOAD_TOO_LARGE-12A bound was exceeded or an explanation output-text buffer is too short; inspect the specific call's contract and required-length output.
INVALID_STATE-13The object's current lifetime or lease does not permit the operation.
STORAGE_TOO_SMALL-14Caller-supplied explanation workspace cannot hold the preparation.

maelys_datalog_status_name() returns the name for a status. Do not parse a human diagnostic message to determine the status, and do not treat any non-OK value as a negative membership result.

Example — document access

The example returns two different kinds of “no”: a failed API call and a successful query in which allow("mallory","roadmap.pdf") is absent. Neither authorizes access.

CODE
int present = 0;
maelys_datalog_status_t status = maelys_datalog_result_query(
    result, "allow", mallory_query, 2u, &present);
if (status != MAELYS_DATALOG_STATUS_OK) {
    fprintf(stderr, "query failed: %s\n", maelys_datalog_status_name(status));
    return DENY;
}
return present ? ALLOW : DENY;

Here mallory_query is the two-symbol array on Querying; ALLOW and DENY are application decisions, not engine status values. A load or solve failure is handled before this code can run.

Diagnostic functions

C · functionSince v0.10.0
Initialize a diagnostic value
maelys_datalog_diagnostic_t
maelys_datalog_diagnostic_initializer(
void
);
Constructs an initialized diagnostic value, including its size and ABI metadata, ready to receive details from an API call.
Arguments
Return value
maelys_datalog_diagnostic_t

Returns a zeroed diagnostic with struct_size and abi_version set for diagnostic ABI 1. MAELYS_DATALOG_DIAGNOSTIC_INIT is the equivalent initializer macro.

C · functionSince v0.10.0
Initialize caller-owned diagnostic storage
maelys_datalog_status_t
maelys_datalog_diagnostic_init(
void * storage,
size_t storage_bytes
);
Initializes diagnostic storage supplied by the application, with the metadata required before passing it to an API call.
Arguments
storagevoid *
Naturally aligned caller-owned storage.
storage_bytessize_t
Available bytes; at least sizeof(maelys_datalog_diagnostic_t) for ABI 1.
Return value
maelys_datalog_status_t

Initializes the known ABI 1 object. Rejects storage that is too small before writing a diagnostic payload.

C · functionSince v0.10.0
Clear a reusable diagnostic
maelys_datalog_status_t
maelys_datalog_diagnostic_clear(
maelys_datalog_diagnostic_t * diagnostic
);
Clears details from a previous diagnostic while keeping the object ready for reuse by another API call.
Arguments
diagnosticmaelys_datalog_diagnostic_t *
Previously initialized diagnostic to reuse.
Return value
maelys_datalog_status_t

Resets the known fields while preserving struct_size and abi_version. This is not secure erasure.

When a diagnostic contains a typed reason code, turn it into a stable textual name for logs. Do not parse the human message to decide control flow.

C · functionSince v0.10.0
Name a diagnostic reason
const char *
maelys_datalog_diag_code_name(
maelys_datalog_diag_code_t
);
Converts a diagnostic reason code into a readable name, complementing the broader public status.
Arguments
codemaelys_datalog_diag_code_t
Typed reason from an initialized diagnostic.
Return value
const char *

Returns a stable reason name suitable for diagnostics; the status remains the call outcome.

For example:

CODE
maelys_datalog_diagnostic_t diagnostic =
    maelys_datalog_diagnostic_initializer();
maelys_datalog_status_t rc =
    maelys_datalog_session_solve_edb(session, edb, &result, &diagnostic);
if (rc != MAELYS_DATALOG_STATUS_OK) {
    fprintf(stderr, "%s: %s\n",
            maelys_datalog_status_name(rc),
            maelys_datalog_diag_code_name(diagnostic.code));
}

{0} alone is not a valid diagnostic initializer in 0.10.0: it leaves struct_size and abi_version unset. Alternatively, call maelys_datalog_diagnostic_init(&diagnostic, sizeof diagnostic) on aligned storage and check its return status. Use diagnostic_clear(&diagnostic) only after initialization when reusing the same object.

The function return value remains the authority. source == NONE means no detail was supplied, even if a diagnostic object was passed. Otherwise status records the associated failure and code names the precise cause. message and hint are bounded human text; do not parse them as an error protocol or serialize the entire struct. Clearing leaves text bytes after the first NUL unspecified.

Read only the sections present

present is a bitmask, not a single choice. For example, a capacity diagnostic may also identify a predicate. Test each bit before reading its fields:

Presence bitRelevant fields
LOCATIONfile, line, column
PREDICATEpredicate, arity
CAPACITYobserved_count, limit, limit_kind
DEPTHdepth, depth_limit
COMPARISONcomparison_result, kind fields, comparison_op
ARITYexpected_arity, observed_arity, term_index
RULErule_id
CONTEXTtoken, field, domain
AGGREGATEfield, token, lhs_kind, term_index, limit

These bit names carry the MAELYS_DATALOG_DIAGNOSTIC_ prefix. Unknown future bits must be ignored; fields from absent sections must not be interpreted. term_index is a zero-based source position when its section supplies one, not a value to recover from the message.

Aggregate rejection in 0.10.0

The two new maelys_datalog_diag_code_t values have stable names:

Codemaelys_datalog_diag_code_name()Meaning
MAELYS_DATALOG_DIAG_SOLVE_AGGREGATE_DOMAIN_ERRORsolve_aggregate_domain_errorA projected value for min, max or sum is not an integer in the accepted range 0–2147483647.
MAELYS_DATALOG_DIAG_SOLVE_SUM_OVERFLOWsolve_sum_overflowThe first partial sum exceeds 2147483647.

Both return INVALID_FIELD and publish no partial result. The AGGREGATE, PREDICATE and CONTEXT sections identify the source relation and value. In AGGREGATE, field names min, max or sum; token contains the offending value (or the first overflowing partial sum); term_index is the zero-based projection argument; and limit is the inclusive numeric bound 2147483647. This is not a storage-capacity error: the CAPACITY bit and limit_get selectors describe a different kind of limit.

The 0.9.1 low-level diagnostic catalog is retained for historical integrations. New code uses this versioned public diagnostic protocol, not the 0.9.1 layout.

Errors and fail-closed behavior

Most operations return maelys_datalog_status_t; name and initializer helpers return their documented values. Convert a returned status to a stable name with maelys_datalog_status_name(). Loading and solving can additionally fill maelys_datalog_diagnostic_t with a source, code, location, phase, message, and hint.