Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Diagnostic codes

The compiler crate oxc-diagnostics holds the authoritative diagnostic catalog (generated.rs), regenerated from the [[diagnostic]] entries in oxc-syntax/grammar.toml. This appendix is generated from the same entries — it cannot drift from the catalog (CI enforces it via cargo xtask check-drift). Where prose elsewhere in the book disagrees with a row here, this table wins.

A code is O[E|W]NNNN — an O-prefix (legacy Ontolog/Oxide; carries through pending a v0.3 rename), a severity letter, and a four-digit number.

The catalog has 270 codes (262 OE + 8 OW), of which 231 are live (a real emitter exists) and 39 are reserved for planned later stages.

SeverityMeaning
OEError: blocks elaboration or load
OWWarning: surfaces, does not block

The Status column distinguishes a live code (a real emitter exists in the toolchain) from a reserved one (declared up-front for a planned later stage, no emitter yet — audit dc-04). A reserved code never fires today; it is listed so the number is claimed and the planned gate is documented. There are no library-namespaced codes (mlt::, potency::, ufo::) in the catalog: a theory package authors its constraints as its own rules/checks over the neutral substrate, never as reserved compiler codes. The MLT reasoning codes that once sat in 19xx are gone for exactly that reason; the 19xx codes that remain are the cross-level instantiation-body field-coverage gates (§5.2), which are substrate-level, not theory-specific.

Range allocation

The number’s leading digits group codes by subsystem. These are conventions for allocation, not a hard partition; ranges with no codes today are omitted.

RangeSubsystem
00xx–01xxParse / syntax; name resolution and imports
02xxType / elaboration / predicate-atom validation; membership-write gates
05xxStratification
06xxMeta calculus, refinement, comparison handling, trait conformance
07xxModules, attributes, temporal/modal, forget
08xxField-modifier gates, world-assumption temporal index, positional construction
09xxWorld-assumption conservativity and placement
10xxCWA evaluation, field intent
11xxBridges
12xxBuild composition + .oxbin validation (§16)
13xxRuntime contract + rule-evaluation gates (§17)
19xxCross-level instantiation bodies
24xxCollection operators

Parse and name resolution (00xx–01xx)

CodeSeverityStatusNameMeaning
OE0001ErrorLiveUnexpectedTokenParser found a token it did not expect at the current position.
OE0002ErrorLiveUnterminatedStringString literal missing its closing ".
OE0003ErrorReservedInvalidNumberLiteralNumeric literal could not be parsed. The INT/REAL literal grammar is §2.5.
OE0004ErrorLiveInvalidEscapeSequenceUnrecognized escape sequence in a string or char literal.
OE0005ErrorLiveUnterminatedBlockCommentBlock comment /* … */ missing its closing delimiter.
OE0006ErrorLiveNonAssociativeChainComparison (== != < <= > >=) and membership (in, not in) operators are non-associative (§6.6): a bare chain like a < b < c is refused at parse. Pre-refusal the parser folded chains left-associatively, so a < b < c became the Bool-vs-Int comparison (a < b) < c — type-mangled, and in a rule body silently never-true (every row dropped under a green check). Write the conjunction explicitly (a < b && b < c); explicit parentheses ((a < b) == c) are accepted as written.
OE0007ErrorLiveQueryClauseNotYetImplementedA query select-body uses a result-shaping clause — group by … having, `order by … asc
OE0008ErrorLiveModifierMisplacedA declaration modifier appears on a form that does not admit it. abstract attaches to metatype declarations (every type the metatype introduces is abstract) and per-type to concept declarations (pub abstract type Vehicle { … }); fixed is metatype-level ONLY (pub fixed metatype kind = { … }; — classification-mutability is a property of the behavior bundle, not of one type). Any other placement — abstract struct, fixed before a concept declaration, a modifier on enum/rel/trait/rule forms, or a repeated modifier — is refused at parse rather than silently dropped: a swallowed modifier would let the program LOOK constrained while the substrate enforces nothing.
OE0009ErrorLiveEnumPipeFormRemovedAn enum declaration uses the `= variant
OE0011ErrorLiveMissingTerminatorA bodyless declaration is missing its terminating ;. A declaration is terminated by exactly one of: its body’s closing } (pub category Animal { … }), its cover’s closing } (pub kind Vehicle { Car, Truck }), or — when it carries neither — a required ; (pub category Top;). This is the same item-termination rule as Rust (struct Foo; needs the ;, struct Foo { … } does not). The terminator used to be optional: with no ; and no body the parser could not tell where the declaration ended, so a following #[…] attribute was silently re-attributed to the prior declaration and mis-expanded, surfacing a wrong, unrelated error far from the cause. Add the ; at the end of the unterminated declaration.
OE0012ErrorLiveCoverPipeFormRemovedA concept declaration uses the `= A
OE0101ErrorLiveUnresolvedNameBare identifier did not resolve to any in-scope declaration.
OE0102ErrorLiveReservedModuleNamestd is a reserved top-level module name; the compiler embeds the stdlib at this namespace. User-declared modules named std would shadow stdlib imports and are refused. Rename the module.
OE0103ErrorLiveUnresolvedUseImportA use a::b::C; import does not resolve to any item in scope. Before this gate a broken use was accepted clean and the only error was a misleading downstream OE0605/OE0101 far from the cause; now the use itself is refused, with a did-you-mean suggestion over the names visible in the target namespace (a dependency package’s pub surface declared in [dependencies], a sibling module, an intra-package pkg::/self::/super:: path). A glob use pkg::*; brings in the target’s pub surface and is never a silent no-op; a glob whose prefix is itself unresolved is the same OE0103.
OE0104ErrorReservedGlobImportUnsupportedReserved (no emitter): a glob use path::*; whose shape is not yet supported. The supported glob — re-export-aware import of a module’s pub surface — resolves; this code is held so a future unsupported glob variant refuses feature-named rather than silently importing nothing.
OE0150ErrorLiveRelationSubsumptionArityMismatchRelation R1 <: R declaration where R1 and R have different parameter counts.
OE0151ErrorLiveRelationSubsumptionEndpointVarianceRelation R1 <: R declaration where an endpoint position’s type in R1 does not specialize (<:) the corresponding position in R.
OE0152ErrorReservedRelationSubsumptionCardinalityViolationRelation R1 <: R declaration where a slot’s cardinality [c..d] does not refine the parent’s [a..b]. Refinement requires c >= a and (d <= b or b = *).
OE0153ErrorLiveRelationSubsumptionMetarelMismatchRelation R1 <: R declaration where meta(R1) != meta(R) (MVP rule — cross-metarel subsumption is deferred).
OE0154ErrorLiveRelationSubsumptionCycleRelation subsumption graph contains a cycle (R1 <: R2 <: ... <: R1) — the substrate requires an acyclic subsumption DAG.
OW0010WarningLiveNonCanonicalClauseOrderA concept declaration writes the : iof-instantiation clause before the <: specialization clause. Both orders parse and mean the same thing — the two clauses are independent (parents are an unordered set on each axis) — so this is a style WARNING, not an error: it never blocks ox check/ox build. The canonical spelling places <: before : (pub subkind Penguin <: FlyingAnimal : Vertebrate_Species { … }), mirroring the order arithmetic — specialization parents sit at the concept’s own order, instantiation parents one above. oxfmt will normalize the order for you once the CST-driven formatter lands; reorder the clauses to silence the warning in the meantime.

Type, elaboration, predicate atoms, membership writes (02xx)

CodeSeverityStatusNameMeaning
OE0201ErrorLiveTypeMismatchExpected one type but found a different one — expected X, found Y.
OE0202ErrorLiveArityMismatchFunction call has the wrong number of arguments.
OE0203ErrorLiveNonExhaustiveMatchmatch arms do not cover every constructor of the scrutinee type.
OE0204ErrorLiveUnknownFieldField access x.f — in a derive/check/bridge rule body or a fn/mutate body — where the receiver’s established type, a struct or concept (pub type ..., or a vocabulary introducer) including inherited fields and any operand : T type-test narrowing in scope (a rule-body type-test or a comprehension where e : T), declares no field named f. In rule bodies, reported only on provable absence: f must be missing from every established concept of the receiver, since an Argon individual may be classified under several concepts (a field on any asserted concept is admitted). Evidence-gated: a base with no established concept (an unbound variable, or a qualified path to a declared type/enum such as Color.red) is skipped.
OE0207ErrorLiveRequiredFieldMissinginsert T { … } omitted a field that T or one of its <: ancestors declares as required at construction (intent Required — not T? / Truth4Of<T> — with neither a default nor a from-navigation source). Emitted by the runtime construct path (oxc-runtime) as a loud refusal with nothing committed, rather than silently minting an incomplete individual. Distinct from OE1014 RequiredFieldUnasserted, the CWA evaluation-time case; the OE0207 number is a known wart pending the v0.3 renumber.
OE0208ErrorReservedAmbiguousFieldFromMultipleParentsReserved (designed — §5.2): a concept declaration (or a field access) names a field declared by more than one parent on the <: or : axis, with no qualifier to pick which. The substrate offers no automatic merge, override-by-position, or last-wins resolution — every collision is resolved explicitly by qualifying the field with its parent (bar.Vertebrate_Species::habitat). This entry reserves the code for the elaborator’s diamond-resolution gate.
OE0210ErrorReservedIofInsertOnRigidTypeReserved (designed, not yet wired — §7.5): a dynamic insert iof(x, T) reclassifying an individual into a rigid type (rigidity::rigidkind, subkind, category) rather than an anti-rigid one (role, phase, mixin). To create a new individual of a rigid type, use insert T { … }. The rigidity gate is not yet wired into the runtime iof path; this entry reserves the code for it.
OE0211ErrorLiveIofInsertOnDefinedinsert iof / delete iof on a defined (iff) concept (or one with a defined <:-ancestor), whose membership is derived from the refinement predicate, not asserted. Update the underlying state instead; the substrate auto-classifies. Emitted by the runtime mutate path (oxc-runtime), including the upward-closed ancestor case (IofInsertOnDefinedAncestor).
OE0212ErrorReservedMetaArgUnboundReserved refusal for an unbound argument position of the type-position reflection intrinsics (meta/iof/specializes/extent). implements is EXEMPT by design: $implements is a finite catalog-closed relation, so both of its positions may be free — enumeration (free t: the implementing types; free tr: a type’s traits) is the intended use. The current engine answers the other intrinsics’ free positions relationally too, by enumerating their materialized $-relations, so this code has no emission site today; it is reserved for argument shapes a future evaluator cannot satisfy relationally.
OE0213ErrorLiveIofInsertIntoBotinsert iof(x, Bot) (or delete iof(x, Bot)) targets Bot/, the empty concept (lattice bottom), which by definition has no instances — the assertion is a contradiction and is refused at ox check / ox build. A sound empty-category refusal that follows from Bot’s definition alone, NOT from concept-vs-concept disjointness (which stays reserved, OE1904). The dual Top/ is the lattice join — every individual is an instance of it — so a rule body Top(x) ranges over the whole domain.
OE0220ErrorLiveFactReferencesUnknownPredicatepub fact P(...) references a predicate name that is not declared as a concept or relation in the module.
OE0221ErrorLiveFactArgArityMismatchpub fact P(args) argument count doesn’t match the declared arity of P (1 for concepts; the relation’s parameter count for relations).
OE0222ErrorLiveFactArgTypeMismatchpub fact P(args) argument shape doesn’t match a declared parameter type (e.g., a literal in a slot that expects an individual).
OE0223ErrorLiveRuleReferencesUnknownPredicateA rule body or head (derive / check / bridge) references a predicate atom P(...) whose head name does not resolve to a declared concept, relation, derive/query/check head, or reflection intrinsic in scope (§7.3.1). Predicate vocabulary must be declared; OWA governs the truth value of instances of a declared predicate, not whether the predicate name itself exists.
OE0224ErrorLivePositionalConceptInsertA positional insert C(...) in a mutate body where C resolves to a concept constructs nothing — parenthesized insert asserts a relation tuple, and the head is a concept, not a relation. Use the brace form insert C { field = value, ... } to construct an individual. Construction is brace-only; parens are reserved for relation-tuple assertions.
OE0225ErrorLiveRuleAtomArgArityMismatchA predicate atom P(args) in a derive / check / bridge rule body or head supplies the wrong number of arguments for the declared arity of P (1 for a concept-as-predicate; the relation’s parameter count for a relation; the head arity for a derived predicate). The non-ground analogue of OE0221 (pub fact), split by context per the OE0220→OE0223 precedent.
OE0226ErrorLiveRuleAtomArgTypeMismatchAn argument to a predicate atom P(args) in a derive / check / bridge rule body or head has a type incompatible with P’s declared parameter type at that position (e.g., a logic variable bound elsewhere to String used in a slot declared Int, or a literal of the wrong primordial). Reported only when both the argument’s type and the parameter type are concretely known. The non-ground analogue of OE0222 (pub fact).
OE0227ErrorLiveRuleValuePathUnresolvedA multi-segment path (a::b) in a rule body resolves to nothing under the unified value-position resolution order (bound rule variable, enum constant, axis value, type reference, declared individual — and, in predicate position, rule heads / concept extents / relations first). Before this gate the lowering silently turned an unresolved path into a VARIABLE named by the joined path — rigidity::anti_rigid then tripped OE1303 as an “unbound variable”, and a path in predicate-argument position bound everything and over-derived. Refused at ox check / ox build instead, naming the path and the namespaces searched. Also fires when a bare A::B rule atom resolves to a CONSTANT (a constant is a value, not a predicate; the path :: Ident metaEq sugar applies only when the left side is a bound term AND constant resolution declines the path), and when a qualified path matches several declarations (qualify further). Fix the spelling, declare the missing symbol, or qualify the reference.
OE0228ErrorLiveRuleValueNameAmbiguousA bare identifier in a rule-body value position is BOTH a rule variable (a head parameter, or a comprehension/quantifier/aggregate binder) AND resolves to a declared constant (a declared individual). Refused naming both candidates rather than silently picking one — the lesson of Rust’s bindings_with_variant_name lint, promoted to a refusal: silently reading it as a variable shadows the constant (the pre-S0 behavior that made knows(x, carol) over-derive); silently reading it as the constant changes the rule’s arity semantics. Rename the variable, or qualify the constant (module::name). A bare identifier that occurs ONLY in body positions and resolves to a declared constant IS that constant — no ambiguity, no error.
OE0229ErrorLiveUnknownFieldWriteA mutate-body write names a field the target concept does not declare: a constructor field (insert C { f: v }), an update … set { f = v } assignment, or an insert … into x.f target, where f is missing from C and from every ancestor in its <: chain. Reported only on provable absence — the concept and its full ancestor chain must be declared in the elaborating file; cross-module targets defer to runtime. Without the gate a typo’d field name persists under a property id no read path resolves — silent data loss.
OE0230ErrorLiveInsertIntoNonCollectioninsert <elem> into x.f targets a field whose declared type is not a collection ([T] / List<T> / Set<T>). insert into appends to collection fields; on a scalar field it would silently replace the committed scalar with a one-element list, corrupting the field’s type and detaching every refinement and derive that reads it. Use update … set { f = … } for scalar writes.
OE0231ErrorLivePropertyIdCollisionTwo distinct Type::field pairs fold to the same property NameRef under the hash-derived property_id_for_field stand-in. Property ids are masked into the INT4 wire band [1, 2^31-1] (the high bit is reserved); the 31-bit space leaves room for collisions at workspace scale (birthday bound ≈ 2^15.5 field identities), and a collision is silent data aliasing — the two fields would share one storage column, the later declaration’s reverse-lookup entry shadowing the earlier. Refused at module load: the closed-set ConceptDecl walk that builds the resolution map is the injectivity oracle, so the collision converts to a build/load refusal naming both pairs instead of corrupting writes. Rename one field, or rebuild once the sequential interning table retires the hash stand-in entirely.
OE0232ErrorLiveRelationEndpointMissingA write places an individual into a typed slot — a relation endpoint or a concept-typed field — that no committed event introduces: a dangling reference. The ruling: such writes REFUSE missing individuals at write time; an individual EXISTS iff some committed event names it (an iof assertion OR a property assertion — full classification is not required, preserving §3.5 domain-conservative ghost-individual semantics). Fires on three surfaces. STATIC: a pub fact R(…, e, …) whose identifier endpoint e is in no concept-membership pub fact C(e) in the elaborating file (build-time, all information in source; cross-module endpoints defer to runtime). RUNTIME (relation): an insert R(…) in a mutate body (or CLI/serve write) whose individual endpoint resolves to an id no iof/property assertion in the store names. RUNTIME (field): an insert C { f: o } / update t set { f = o } whose concept-typed field f is given an individual o that no committed event names — the field-side counterpart of the relation endpoint floor, since a concept-typed field is a typed slot exactly as an endpoint is. Both runtime surfaces are checked against the overlay’s read-your-writes view, so an individual constructed or classified earlier in the SAME body counts. Without the gate, a relation’s declared signature (or a field’s declared type) is decorative: derives joining serve rows whose endpoints are in no extent, and a forged below-floor #i reference would slip past the serve floor-bound. Atomic — raised before the tuple/field is buffered, so the whole body commits nothing. Existence is the FIRST gate; TYPING is the layer above it (OE0258): once the individual exists, a closed-world target concept refuses a write over an UNclassified individual (CWA cannot silently expand a closed extent), while an open-world concept admits it. delete iof-driven cascade is a recorded non-decision (deferred). Construct or classify the individual first, or fix the reference.
OE0233ErrorLiveAbstractTypeConstructThe program asserts a direct instance of an abstract type: insert T { … } where T is declared abstract (or is introduced by an abstract metatype), a direct insert iof(x, T) classifying an existing individual under it, or a positive pub fact T(x) seeding one at elaboration. abstract means NO DIRECT INSTANCES — abstract types structure the hierarchy (and are exempt from trait impl-coverage obligations, OE1327) precisely because every individual is classified through some non-abstract subtype. Assert or classify under a non-abstract subtype instead; subtypes are unaffected, and pub not_fact T(x) (refuting membership) stays legal. Emitted at ox check/ox build where the target is statically known; the runtime enforces the same refusal at the write path (atomically — the whole mutation rejects) for targets only resolvable at execution, and at artifact load for hand-built IofAssertion events that would bypass the elaborator.
OE0234ErrorLiveFixedReclassificationA mutate body re-classifies under a type introduced by a fixed metatype: insert iof(x, T) or delete iof(x, T) where T’s introducing metatype is declared fixed. fixed means classification is DECIDED AT CONSTRUCTION — membership of fixed-introduced types never changes over an individual’s lifetime, which is what makes static check discharge over them sound (§10.2: rigid designation = fixed classification). Construction (insert T { … }) is NOT re-classification and is unaffected; types introduced by non-fixed metatypes classify and de-classify freely (dynamic is the default — the restriction is the opt-in, the same posture as check). Emitted at ox check/ox build where the target is statically known; the runtime write path enforces the same refusal (atomically) otherwise. Importing a vocabulary can never change mutation semantics by axis NAME — only the declared fixed modifier carries this behavior.
OE0235ErrorLiveGenericTypeApplicationUnsupportedA generic type application carries arguments the elaborator does not interpret. User-declared concept generics are decorative: a concept’s <T> parameters parse but reach no storage slot (ConceptDeclBody has no type-parameter column), so an application like Boxy<Int> / Boxy<Int, String, Bool> / a bare Boxy (arity 0 against a 1-param concept) / NotGeneric<Int> (arguments on a non-generic concept) was accepted with the arity and applicability silently discarded — the §6.2 ‘generic applications subtype only by equality’ rule and the §6.1 bounded-generic grammar both imply the arguments are semantically real. The library generics with a real construction surface are unaffected (List<T>, Set<T>, Option<T>, Result<T, E>, Range<T>, Truth4Of<T>, and the live reflective TypeRef<C>); their argument shapes ARE interpreted. Refused at ox check / ox build at the use site until parameterised user concepts are real (the type-parameter plane is V1 bounded-generics territory). Drop the arguments, or use one of the supported library generics.
OE0236ErrorLiveMutateFieldValueTypeMismatchA value position in a mutate body is assigned to a declared field whose type it does not match: an update target set { f = v } whose v is a value of a primordial incompatible with f’s declared type (a String into an Int field, an Int into a Date field, a structured CBOR record into a scalar field). Pre-refusal these assignments bypassed any runtime re-check (the write path’s coerce_value_for_declared_type was temporal-coercion-only, falling through other => Ok(other) for the mismatch), so the wrong-typed value committed and downstream rules derived silently-wrong rows (an Int in a Date field made d < <date> unconditionally true under the cross-type comparison fallback — see OE0630). Emitted at ox check / ox build for the statically-decidable, sound subset — a primitive literal whose primordial type UNCONDITIONALLY contradicts the field’s declared primordial type (the constructor insert C { f: lit } and update target: T set { f = lit } paths), refused before a doomed artifact is built rather than late at query/serve. The static gate is a STRICT SUBSET of the runtime gate: value-dependent pairs the runtime may coerce (a String literal into a parse-coercible temporal / exact-numeric field, an Int into the numeric tower or Duration day-count, an integral Real into Int/Nat) stay deferred to the runtime mutate value path, which remains the backstop for those and for cross-module field-type chains. The Value::Cbor carrier seam is bounded by tag inspection: a tag-30 exact rational is checked against the numeric tower (accepted into Real/Decimal/Money/Int, refused into Date/Duration/String/Bool), and a structured map/array/enum-payload carrier is refused into the NATIVE primordials that never ride a structured carrier (Int/Nat/Real/Date/Duration/String/Bool) — a Money struct into Int is the canonical refusal. Money and Decimal are EXEMPT: today they are represented AS opaque/structured CBOR carriers, so a structured value is their legitimate form; an indecodable opaque blob or a concept-typed field also passes through. The field-coercion path (TextDate/Duration/Real parse, IntDuration day-count) stays accepted where the surface defines it.
OE0237ErrorLiveFieldDefaultUnsupportedA field declaration carries a default-value clause field: T = expr. Book §5.1 specifies full default semantics (lazy evaluation at access, self resolution, resolution order), but the elaborator never reads the expression — the parser consumed it as token soup and the lowering hardcoded default: None, so the default silently never applied: a required field with a dropped default still refused construction (OE0207), and an optional field T? = expr constructed successfully with the default absent (silently wrong extents downstream). Refused at parse until the lazy-default evaluator lands rather than accepting a clause the substrate ignores. Drop the = expr and supply the value at construction, or use a from-navigation source (field: T from Rel.endpoint) for a derived value. The from-clause form is unaffected — it is parsed and elaborated.
OE0238ErrorLiveUpdateOnUnclassifiedupdate … set { … } targeted an individual that is an instance of no concept at all — its classification set is empty. A primitive (where) concept’s necessary invariant is keyed on a classifier, so an unclassified target evaluates none of them: the field write proceeds wholly unchecked and the corrupt value silently resurfaces (bypassing the invariant) if the individual is later classified into a concept the value violates. Refused loudly by the runtime mutate path (oxc-runtime) rather than written — classify the individual first (insert iof(x, T) or construct it with insert T { … }), then update. Atomic: nothing flushed. Scoped fix; re-validating all properties at classification time is a separate follow-up.
OE0239ErrorLiveFactReferencesDerivedPredicatepub fact P(...) names P, a predicate defined by a pub derive / pub query rule (an intensional / IDB head), not a base predicate. pub fact asserts into an EXTENSIONAL relation (a concept-as-classification or a pub rel); a derived predicate’s extent is COMPUTED by rule derivation, and a pub fact seed would key a different relation node than the rule head reads, so it silently DROPS OUT of the fixpoint (no error, wrong answer). Refused at ox check / ox build rather than emitting an artifact that mis-derives. To give a derived predicate ground tuples that participate in its derivation, use one of the two sanctioned forms: (1) a bodiless pub derive P(args); clause — a derive head with no :- ... body over CONCRETE arguments is itself a ground fact that unions with P’s other derive clauses and rules over the same head; or (2) declare a base relation the rule reads — pub rel Base(...), seed it pub fact Base(...), and add a pub derive P(...) :- Base(...) clause. Either keeps P a single-origin intensional head; pick the bodiless-derive form to seed P directly, the base-rel form when the seed tuples are themselves a reusable extensional predicate.
OE0240ErrorLiveGroupAxiomDisjointOverlapA disjoint { A, B, … } group axiom declares its members pairwise non-overlapping, but a write would classify one individual into two of them at once (iof(x, Ai) and iof(x, Aj)). The membership is refused at the write rather than admitted, since an individual in two declared-disjoint siblings makes the partition contradictory and every downstream query over either sibling silently wrong. Carried by a compiler-synthesized check (one per unordered member pair) whose runtime delta-guard refuses the offending insert. Instance-level under the closed-world default (§6.9). #[world(open)] is a live concept attribute, but this disjoint delta-guard evaluates closed-world regardless of the concept’s world — the open-world tolerate softening is designed and not yet wired (the runtime guard does not read the per-concept world map). Retract the conflicting membership, or remove the member from the disjoint set if the overlap is intended.
OE0241ErrorLiveGroupAxiomUncoveredA complete Parent { A, B, … } (or partition) group axiom declares its members jointly exhaustive over Parent, but a write would create a Parent instance that is a member of none of them (iof(x, Parent) with not iof(x, Ai) for every cover member). Under the closed-world default (§6.9) the negation-as-failure covering guard fires when no child membership is derivable, and the write is refused rather than admitting an uncovered Parent instance the cover claims cannot exist. Carried by a compiler-synthesized check whose runtime delta-guard refuses the offending insert. #[world(open)] is a live concept attribute, but this covering delta-guard evaluates closed-world regardless of the concept’s world — the open-world tolerate (permit-as-unknown) softening is designed and not yet wired (the runtime guard does not read the per-concept world map). Classify the instance into one of the cover members, or widen the cover.
OE0242ErrorLiveGroupAxiomUncoveredSubtypeA complete Parent { A, B, … } (or partition) group axiom declares its members jointly exhaustive over Parent, but the schema declares a NON-abstract concept S <: Parent (transitively) that specializes none of the cover members — a provably-uncovered instantiable class. Any instance of S is a Parent instance in no cover member, so the cover is statically incomplete. Refused at build by a direct elaboration pass over the <: graph (not a reasoner check — instantiable has no catalog atom to range over). An ABSTRACT subtype is exempt: it has no direct instances, so it cannot witness an uncovered instance. Add S (or one of its supertypes inside the cover) to the cover, mark S abstract, or interpose a cover member S <: Ai.
OE0243ErrorLiveGroupAxiomNonSubtypeChildA complete Parent { …, S, … } (or partition) group axiom names a cover member S that is not a subtype (<:, transitively) of the declared Parent. A cover’s members partition the parent’s extent, so a non-subtype member could classify individuals outside Parent — the covering / disjointness guards would then range over the wrong extent. Refused at supertype resolution. disjoint { … } has no parent and imposes no such constraint. Declare S <: Parent, or remove S from the cover.
OE0244ErrorLiveFromClauseUnknownRelationA navigation-view projection field (field: T from Rel.endpoint) names a relation Rel that does not resolve to a declared pub rel in scope. The from clause projects the field’s value from one endpoint of that relation, so a relation that is not in scope leaves the field projecting nothing — and the clause was previously never checked: only the runtime read from_relation, so a bogus relation built clean and silently projected an empty view. The relation path is now resolved at ox check (the same name-resolution gate concept/relation references pass), and an unresolved or non-relation head is refused. Declare the relation, import it (use), or correct the path.
OE0245ErrorLiveFromClauseUnknownEndpointA navigation-view projection field (field: T from Rel.endpoint) names an endpoint accessor endpoint that is not one of the relation Rel’s declared endpoint names (nor the positional domain/range aliases for the first/last endpoint of a binary relation). The endpoint selects which relation position the field projects; an accessor that matches no position projects nothing — and was previously unchecked (only the runtime read it, so a bogus endpoint built clean and silently projected an empty view). The accessor is now validated against the relation’s declared positions at ox check. Use one of Rel’s declared endpoint names, or domain/range.
OE0246ErrorLiveFromClauseEndpointTypeMismatchA navigation-view projection field (field: T from Rel.endpoint) declares a field type T whose concept is <:-incomparable with the type E of the relation endpoint it projects — neither is a subtype of the other. A navigation view is type-directed: it projects the endpoint and keeps the members that are iof T, so the view is sound for any <:-comparable (T, E) pair (identity when T == E, a no-op widening when E <: T, a real iof T filter when T <: E). But when T and E are unrelated, no endpoint value can be iof T: the view is statically empty and the declaration is type-incoherent. (The narrowing case T <: E — e.g. circles: [Circle] from Contains.shape over a Shape endpoint — is now ACCEPTED and filters to the T-typed members; it no longer errors here.) Widen the field type to a supertype of E, or project an endpoint whose type is <:-comparable with T.
OE0247ErrorLiveFromClauseFilterContradictionA navigation-view projection field (field: T from Rel.endpoint where <predicate>) carries an explicit where type-test endpoint : C whose concept C is <:-incomparable with the field’s element type T. The type-directed view already keeps only the iof T members; a where endpoint : C restates or narrows that selection and must be CONSISTENT with it. When C and T are unrelated, the conjunction iof T && iof C is unsatisfiable: the view is statically empty. A consistent restatement names T itself (where shape : Circle on a [Circle] field) or a <:-related concept; a value predicate (where shape.radius > 0) imposes no such constraint. Drop the contradictory type-test, or align it with the field type.
OE0248ErrorLiveFieldValueNotIndividualA write to a concept-typed field supplies a primitive value where an individual is required: a constructor field (insert C { f: <literal> }) or an update … set { f = <literal> } assignment whose declared field type f: D is a declared CONCEPT, given a primitive literal (a string / integer / decimal / boolean). The value-vs-individual mismatch is the one HARD-CATEGORY refusal sound under Argon’s open-world, multiply-classified semantics (the same arm as OE0222 for pub fact relation endpoints): a value is never an individual of any concept, so it can never inhabit a concept-typed slot — storing it would key a property the read path resolves to a non-individual, silently violating the declared shape. The symmetric arm (an individual written to a primitive-typed field) is also refused. This is NOT a concept-vs-concept disjointness check: an individual of any concept supplied to a concept-typed field is ACCEPTED (it may be reclassifiable; two concepts are never provably disjoint without a declared partition). Supply an individual reference (a constructed binding, a parameter, or a declared individual) for the concept-typed field, or give the field a primitive type if a value was intended.
OE0249ErrorLiveStructFieldMissingA struct VALUE literal T { … } omits a field that T declares: a struct is pure data with structural equality (§5.1), so a literal states every field — there is no construction-time default (field: U = expr defaults are a separate, refused surface). The omitted field’s name and declared type are named. Add the missing field: value, or, when constructing from an existing value of the same struct, use functional update T { ..base, field: value } so the base supplies the rest.
OE0250ErrorLiveStructFieldExtraA struct VALUE literal T { … } supplies a field that T does not declare. A struct is closed data (§5.1): only declared fields may be initialized, and an unknown field is a typo or a stale field name rather than an extension point. Remove the field, or correct it to one of T’s declared field names.
OE0251ErrorLiveStructFieldTypeMismatchA struct VALUE literal T { field: value } initializes a field with a value whose type does not match the field’s declared type. A struct is pure data with structural equality (§5.1); storing a mistyped field would make two values compare unequal-by-type or derive a silently-wrong projection, so the mismatch is refused at build time, naming the field, its declared type, and the supplied type. Supply a value of the declared field type.
OE0252ErrorLiveInsertOfStructinsert T { … } names a struct, but insert constructs a concept INDIVIDUAL — it mints an identity and records an iof classification. A struct is pure data with no metatype and no identity (§5.1): it is constructed as a plain VALUE T { … } (e.g. a let binding, a field value, an argument), never inserted. Drop the insert keyword to construct the struct value, or name a concept type if an individual was intended.
OE0253ErrorLiveMutOnStructFieldA struct field is declared mut. A struct is an IMMUTABLE pure value (§5.1): its fields are fixed at construction and updated only by functional update T { ..base, field: new }, which yields a NEW value rather than mutating in place. The mut modifier marks a concept field updatable by an update … set { … } statement — a notion that applies to identity-bearing concept individuals, not to struct values. Remove mut from the struct field.
OE0254ErrorLiveStructFieldAccessUnknownField access v.f where v is a struct VALUE whose declared struct type has no field f (§5.1). A struct projects field-wise off its declared fields; an absent field is a typo or a stale name. Use one of the struct’s declared field names.
OE0255ErrorLiveStructValueIntoNonStructFieldA struct VALUE is supplied where a field of a different type is declared: a struct value S { … } written to a field whose declared type is a primitive, a concept, or a different struct/enum type. A struct value has structural equality and no identity (§5.1), so it inhabits only a field declared with its own struct type — storing it into an incompatible field would key a value the read path cannot interpret. Supply a value of the declared field type, or change the field’s type to the struct type if the struct value was intended.
OE0256ErrorLiveEnumPayloadArityAn enum payload-variant construction Variant(args) supplies a number of arguments other than one. A payload variant carries a single value (§5.1) — the tag-1011 value carrier holds one payload slot — so Some(7) is well-formed while Some() (zero) and Some(1, 2) (two) are not; the surplus or missing argument is refused rather than silently dropped or truncated. Supply exactly one payload value, or construct a payloadless variant (None) with no parentheses.
OE0257ErrorLiveEnumPayloadPatternA payload-binding match arm Variant(binder) does not bind exactly one fresh variable: a zero-binder Variant(), a multi-binder Variant(a, b), a nested non-binding sub-pattern, or the record form Variant { … }. A payload variant carries one value (§5.1), so its destructuring binds exactly one fresh variable positionally — write Variant(x) => …. Rewrite the arm with a single binder, or match the variant without binding by hoisting the test.
OE0258ErrorLiveRelationEndpointTypeClosedA write places an individual into a typed slot — a relation endpoint (insert R(…)) or a concept-typed field (insert C { f: o } / update t set { f = o }) — that EXISTS (OE0232 passed) but is classified under NOTHING — a bare/ghost individual known only by a property assertion — while the slot’s declared concept T is governed by the CLOSED-world assumption (§6.9). Under CWA concept membership is closed (absence of evidence is evidence of absence), so admitting the write would silently mint the first membership claim about the individual and expand T’s closed extent — refused, the typing layer above OE0232’s existence-only gate. The world assumption DECIDES this arm and nothing else: an OPEN-world T admits the same write (membership assumed-as-unknown), with no diagnostic. Membership is the individual’s full classification (asserted iof UNION derived iff, <:-closed — the decision query_extent/$meta/dispatch share), read against the overlay’s read-your-writes view, so classifying the individual earlier in the SAME body satisfies the gate. Only genuine CONCEPT slots are checked — a primordial position (rel R(a: String, …)) or a primitive field has no extent and is skipped (a primitive into a concept field is the distinct OE0248 value-vs-individual refusal). The Reserved boundary (OE1904) demarcates this gate precisely: when the individual IS classified, but under a concept disjoint from T only by intent (the reversed case — o is iof Pet, the slot wants Person), the write is ACCEPTED, because two concepts are never provably disjoint without a declared partition. Atomic — raised before the write is buffered, so the whole body commits nothing. Classify the individual under {concept} first (this same mutate body counts), or declare {concept} open-world if its membership should be assumable from a write.

Stratification (05xx)

Reserved range — the stratifier’s pre-runtime aggregate diagnoses. The runtime equivalents fire as OE13xx rule-compile gates today.

CodeSeverityStatusNameMeaning
OE0510ErrorReservedNonStratifiedAggregateReserved (designed, not yet emitted as OE0510 — §7.2): a stratified aggregate that would loop through an aggregation step on its own stratum (no well-defined fixpoint). The runtime today refuses recursion-through-aggregation as OE1317 RecursionThroughAggregation at the rule-compile gate; this 05xx code is reserved for the stratifier’s pre-runtime diagnosis of the same shape.

Meta calculus, refinement, comparison, traits (06xx)

CodeSeverityStatusNameMeaning
OE0605ErrorLiveUnknownMetatypeA concept declaration’s introducer (the identifier before the concept name — pub <introducer> Name) does not resolve to a pub metatype visible in scope. Introducers are not keywords: per §3.4 the leading identifier resolves against pub metatype declarations — declared in this package or brought into scope by a use/the package prelude (§5.2). Nothing is ambient: even the baseline type (and rel for relations) must be in scope — add use std::core::{type, rel}; or list prelude = ["std::core::{type, rel}"] under [package]. Two fixes: bring the baseline into scope and use the ontology-uncommitted pub type Person;, or declare/import the vocabulary the introducer belongs to (pub metatype kind = { }; makes pub kind Person legal). Vocabulary classifiers (UFO’s kind, BFO’s class, …) are package vocabulary, not language surface — std::core’s own docs: type is the no-commitment baseline; vocabulary packages ship alternative metatypes.
OE0606ErrorLiveUnknownMetarelA relation declaration’s introducer (pub <introducer> Name(...)) does not resolve to a pub metarel visible in scope. Per §3.4 the leading identifier resolves against pub metarel declarations — declared in this package or brought into scope by a use/the package prelude (§5.2). Nothing is ambient: even the baseline rel must be in scope — add use std::core::{type, rel}; or list prelude = ["std::core::{type, rel}"] under [package]. Two fixes: bring the baseline into scope and use the neutral pub rel Owns(owner: Person, thing: Asset);, or declare/import the vocabulary the introducer belongs to (pub metarel mediation<E1, E2>(e1: E1, e2: E2); makes pub mediation Involves(...) legal). Relation-vocabulary classifiers (UFO’s mediation, material, …) are package vocabulary, not language surface.
OE0612ErrorReservedOptionComparisonRequiresHandlingRule body contains Option<T> comp_op T (or comp_op Option<T>) without explicit None-handling. Use is Some(a), a comp_op ... / `.is_some_and(
OE0613ErrorReservedTruth4ComparisonRequiresHandlingRule body contains Truth4Of<T> comp_op T without explicit four-valued handling. Use is Is(a), a comp_op ... / is Not / is Can outcome suffixes, or match { Is(a) => ..., Not => ..., Can => ..., Both => ... }.
OE0620ErrorLiveAxisValueNotInAxisDomainA rule-body value position names an axis value (rigidity::anti_rigid — a path whose first segment resolves to a visible pub metaxis declaration) that the axis’s declared domain does not admit: either the value is not a member of the enumerated domain (the diagnostic lists the declared values), or the axis declares a TYPED domain (pub metaxis weight for metatype = Real;), whose values are literals with no enumerated-symbol spelling. A valid enumerated axis value never reaches this code — it lowers to a Value::Symbol constant (owner = the axis identity, ord = the chain position) and evaluates against the catalog-closed $axis relation. (Pre-S3 this code refused EVERY axis value as not-yet-evaluable; that scope is retired — the rule-body diagnostic that remains is exactly the not-in-domain / typed-domain-spelling case.)
OE0621ErrorLiveUnknownMetaxisA metatype / metarel body binds an axis (axis: value) whose axis name does not resolve to a visible pub metaxis declaration — or matches several, in which case every candidate is named and a qualified spelling (vocab::rigidity: rigid) disambiguates. Axes are not ambient vocabulary: declare the axis in this package (pub metaxis rigidity for metatype { anti_rigid < semi_rigid < rigid };) or import the vocabulary package that declares it. Pre-S1 these bindings were parsed and silently DROPPED; now every binding resolves to the declaring metaxis’s identity and is persisted on the wire, so an unresolvable axis is a hard refusal, never a phantom.
OE0622ErrorLiveAxisValueNotInDomainAn axis binding’s value is not a member of the axis’s declared domain. For enumerated domains ({ a, b } unordered or { a < b < c } chain) the axis: value binding must name one of the declared values — the diagnostic lists them. Binding an enumerated axis with a literal (axis: 1.5), or a typed axis with a bare symbol (axis: rigid), is the same refusal: the value shape follows the domain (a bare symbol for enumerated domains, a literal for typed ones).
OE0623ErrorLiveAxisLiteralTypeMismatchA typed-domain axis binding’s literal does not satisfy the axis’s declared TypeExpr (or statically fails its where { … } refinement) — e.g. weight = "heavy" against pub metaxis weight for metatype = Real where { _ > 0.0 };. Checked statically for the primitive domains (Int / Nat / Real / Decimal / String / Bool); a refinement comparing the placeholder _ against a literal is also discharged statically. Domains the elaborator cannot decide statically are not refused here (they validate when the $axis relation materializes, slice S3).
OE0624ErrorLiveAxisTierMismatchAn axis is bound on a declaration tier its for targets do not include: a pub metaxis … for metatype axis binds only inside metatype bodies, for metarel only inside metarel bodies. Axes declared for individual / for macro currently bind NOWHERE — those binding surfaces do not exist yet, so a metatype/metarel binding against such an axis is refused with this code rather than silently accepted against a tier that can never consume it. Fix: bind an axis whose targets include this declaration’s tier, or extend the axis’s target list (pub metaxis a for [metatype, metarel] { … };).
OE0625ErrorLiveDuplicateAxisBindingA metatype / metarel body binds the same axis twice (e.g. { rigidity: rigid, rigidity: anti_rigid }) — malformed per the §4 distinct-axes well-formedness constraint (Argon.MetaCalculus.Wellformed.MetatypeDecl.axesDistinct). Axis assignment is functional per (declaration, axis): a second binding could only restate or contradict the first, so both occurrences are named and the declaration is refused. Two spellings of one axis (bare rigidity and qualified vocab::rigidity) count as duplicates — identity is the RESOLVED axis.
OE0626ErrorLiveMetaxisDeclMalformedA pub metaxis declaration’s shape is malformed: an enumerated body mixes , and < separators (a domain is either unordered { a, b } or a chain { a < b < c }, never both); the body is empty or absent (an axis with no domain admits no value, so every binding against it would be refused — declare the values or the typed domain); a value is repeated; the for target list is empty or names something other than metatype / metarel / individual / macro. The declaration is refused at ox check / ox build so the wire never carries a domain the validator cannot interpret.
OE0627ErrorLiveSymbolComparisonUnorderedAn ordered comparison (< <= > >=) over symbol values that carry no common chain order: the operands belong to DIFFERENT owners (different metaxes / different enums — chain order is per-owner), the owner declares an UNORDERED domain ({ a, b } — declare a chain { a < b < c } to compare by order), or a symbol is ordered against a non-symbol value. Emitted at ox check / ox build when both operands are statically known (axis-value / enum constants, or an axis projection whose axis identity is known); the reasoner and the mutate path refuse the same comparison at runtime under the same code — never the enum-variant-order fallback, never a silent row drop. Equality (== / !=) stays defined everywhere: symbols are equal exactly on (owner, name) identity.
OE0628ErrorLiveReflectiveProjectionSortAmbiguousA field projection base.name the sort-directed reading cannot dispatch soundly: (a) name resolves to a visible pub metaxis but the SORT of base is statically UNDETERMINED (or the body pins it to two contradictory sorts) — a Metatype-sorted base reads the metaxis through the $axis relation (meta(t).rigidity with t: TypeRef), while a TypeRef- or individual-sorted base reads a declared FIELD named name (the §5.2 kind-field walk-up); two different relations, so guessing would silently answer the wrong question; fix it by making the base’s sort explicit — annotate the head parameter (t: TypeRef / m: Metatype), or bind the base with a sort-determining catalog atom (m : Metatype, iof(t, kind), an equality with a sorted variable — Var == Var equalities propagate sorts). (b) the base IS Metatype-sorted but no visible metaxis is named name — metatypes carry axis bindings, not fields, so the $field:: join would be silently empty; declare/import the metaxis, or project the field from a type or individual. A projected name matching SEVERAL visible metaxes on a Metatype-sorted base is refused through the axis resolver’s ambiguity arm (OE0621).
OE0629ErrorLiveAxisAssignmentConflictTwo same-precedence $axis assignments disagree for one (target, axis) pair at module load (the effective axis relation is functional — a metatype binding may be overridden by a per-target meta_property event, but two conflicting assignments at the SAME precedence level have no defined winner, so the module refuses to load rather than silently pick one). No surface form double-asserts today (duplicate axis bindings refuse at OE0625; duplicate #[order] refuses at elaboration); this code is the artifact-trust backstop for hand-built or corrupted event logs. Emitted by oxc-runtime at load; declared here so appendix C and ox diagnostics carry it.
OE0630ErrorLiveIncomparableValueTypesAn ordered comparison (< <= > >=) is evaluated between two values whose types carry no common order: e.g. an Int against a Date, a number against a Text. Pre-refusal the reasoner’s value_order fell back to the derived Ord of the Value enum — comparing by variant discriminant — so a mistyped field (an Int stored in a Date field, OE0236’s runtime cousin) made field < <date> unconditionally true and field > <date> unconditionally false regardless of the actual values, silently deriving wrong rows. Now a loud ReasoningError, parallel to the existing temporal-mismatch (TemporalTypeError) and unordered-symbol (OE0627) refusals, raised in both the rule evaluator and the mutate value path — never the enum-variant-order fallback, never a silent row drop. Equality (== / !=) stays defined across types (distinct types are simply unequal) and never routes through the ordering refusal — only the four ordering operators can raise OE0630. Numeric ordering across the exact-numeric tower is defined for the Int/Real carriers (and Decimal/Money operands that ride a Value::Real/literal at evaluation): both promote to a common BigRational and compare by value. A Money/Decimal value stored as an opaque Value::Cbor carrier does NOT decode to a rational at the ordering site — it byte-compares as an unordered structured carrier and is refused (OE0630), not silently mis-ordered; ordering stored exact-decimal carriers is the recorded follow-on, not a v0 guarantee.
OE0631ErrorLiveMetarelEndpointMetatypeMismatchA relation declared via a metarel introducer (pub mediation Involves(m: Marriage, p: Person)) has an endpoint whose metatype does not match — and is not a sub-metatype of — the metatype the classifying metarel declares at that position (§4.3). A pub metarel mediation(mediator: relator, mediated: kind) requires position 0 to be relator-sorted and position 1 kind-sorted; an endpoint introduced under any other metatype (or a non-sub-metatype) is refused. The §4.3 promise — “the elaborator verifies the relation’s endpoint metatypes match the metarel’s positions” — was previously prose only: the position metatype names were parsed and discarded, so a wrong-sorted endpoint (Gustavo’s inheresIn(v: Vehicle, …) where an ability must inhere via an aspect, not a kind) checked clean. The check is catalog-driven and axis-name-agnostic — it compares resolved metatype identities, never a metatype/axis name string. A metarel position naming a primordial or a generic parameter (the stdlib rel<E1: metatype, E2: metatype>) imposes NO constraint; the gate fires only when both the position metatype and the endpoint metatype are known and incompatible.
OE0632ErrorLiveReflectionOnUnclassifiedA reflection intrinsic (meta / iof / specializes / extent) is applied to a struct- or enum-declared carrier — language-level DATA, not an ontologically-classified concept (§4.4.2). Language data carries no metatype, so meta(p) == Point over a pub struct Point is a category error, parallel to OE1016 (Truth4OfOnStruct) for the Truth4 surface. The discipline §4.4.2 leans on (“calling meta() on a struct/enum-declared value is a category error … emits a diagnostic at elaboration”) was previously unenforced — the call checked clean and a vocabulary author writing nonsensical reflection over plain data got zero feedback. Reflection applies only to concepts introduced under a vocabulary or stdlib metatype; classify the carrier under a metatype, or drop the reflection.
OE0633ErrorLiveMetarelEndpointArityMismatchA relation declared via a metarel introducer (pub mediation Involves(m: Marriage, p: Person)) has a different number of endpoints than its classifying metarel declares positions (§4.3). A pub metarel mediation(mediator: relator, mediated: kind) declares two positions, so a relation introduced under mediation must have exactly two endpoints — a ternary mediation R(a, b, c) and a unary mediation R(a) are both refused. The §4.3 endpoint-verification step zipped the relation’s endpoints against the metarel’s positions and silently continued past any position beyond the metarel’s arity, so an over- or under-arity relation checked clean (its surplus or missing endpoints were never validated). The guard is arity-EQUALITY against the metarel’s declared endpoint count — the generic stdlib rel<E1: metatype, E2: metatype> declares two positions and still accepts exactly its two endpoints; a metarel whose positions are all unconstrained (None) still requires the matching count. It is not relaxed to “accept anything”: a metarel imposing no per-position metatype constraint still pins the arity. Forward-compatible — only relaxes if metarel genericity (variadic positions) later lands. Mirrors arityEqual (Argon.Substrate.RelationSubsumption) and the OE0150 relation-arity precedent.
OE0634ErrorLiveAxisSetFormMismatchA metaxis binding uses the wrong form for its domain’s arity. A set-valued domain (pub metaxis restrictedTo for metatype = [ Nature ]) binds ONLY with the set form axis: [a, b]; a scalar domain (enumerated { … } or single Typed) binds ONLY with a single axis: value. Crossing the two — a scalar value against a set domain, or […] against a scalar domain — is refused here. This consolidates what were divergent, non-agreeing refusals for one need: a set binding against a scalar domain previously tripped OE0626 (“expects a value, found [”), and a single value against a set domain tripped OE0622 — separate codes for “you used the wrong binding shape.” OE0634 is the single FORM gate; a set MEMBER that fails the element type / refinement is OE0623 (the per-element type check), not this. Emitted at elaboration and re-checked at artifact load (a crossed form reaching the runtime is a wire inconsistency). The set form is admitted only by a set-domain axis (AxisDomainBody.admitsArgon.Storage.AxisBindingValid).
OE0660ErrorLiveRefinementUnsupportedFormA concept’s where { … } refinement predicate contains an expression form the v0.1 evaluator doesn’t support. Supported forms: literals, self/identifiers, field projection self.field, binary ops (arithmetic / comparison / && / `
OE0667ErrorLiveTraitImplBoundsNotSupportedGeneric-parameter trait bounds on pub trait or impl blocks are reserved syntax but not yet implemented in v0.1. The conditional-impl coherence theorem (Argon.TypeSystem.Conditional) admits multi-impl resolution under disjoint bounds; the elaborator side ships in V1. Use pub trait T<U> / impl<U> Type (without bounds) for now.
OE0668ErrorLiveRefinementInvariantViolatedA membership write would place an individual in a primitive (where) concept whose necessary invariant it positively violates — the predicate evaluates to a definite false. unknown permits the write (information absence, not violation). Checked when a primitive-where member is created by insert iof, by construction (insert T { … }), or when an update writes a field the predicate reads. Emitted by the runtime mutate path (oxc-runtime); the same exact value tower as every other value position.
OE0670ErrorLiveImplMemberMissingAn impl Trait for Type does not provide a member its trait declares (completeness). Every trait member is an obligation: a missing rule-plane member would leave the member predicate without a clause for this target, so calls covered by this impl would silently derive nothing. Provide the member with a full body, or remove the impl.
OE0671ErrorLiveImplMemberExtraneousAn impl Trait for Type provides a member the trait does not declare, or provides it with a different signature — arity, parameter types modulo Self, return type, or plane (derive/check/query vs fn/mutate). The trait owns the member contract; an impl can neither extend it nor reshape it. Bare impls (impl Type { … }) are exempt — they carry no contract (§5.4).
OE0672ErrorLiveOrphanImplViolationAn impl Trait for Type lives in a package that declares neither Trait nor Type (§12.4’s reserved orphan rule, now real). Allowing orphan impls would let two packages give one (trait, type) pair conflicting clauses with no owner to arbitrate. Move the impl into the package declaring the trait or the one declaring the type. v0.1 compiles a single user package plus the stdlib, so this fires today only for impls pairing a stdlib trait with a stdlib type; it activates fully with multi-package composition.
OE0673ErrorLiveImplTargetsOverlapTwo impls of one trait have overlapping targets: the targets are <:-comparable, or they share a declared common descendant (coherence). Overlap would put some declared type under two clauses, so clause selection would no longer be single-valued per declared type — and specialization (“more-specific impl wins”) is rejected by design. impl T for Person + impl T for USPerson is the comparable arm (write disjoint targets, or one impl whose body branches); impl T for Person + impl T for Customer with pub type Employee <: Person, Customer declared is the common-descendant arm.
OE0674ErrorLiveSupertraitUnsatisfiedAn impl Sub for T exists but a supertrait of Sub has no impl covering T. Supertraits are requires-constraints, Rust-exact: pub trait Sub: Super makes impl Sub for T well-formed only when some impl Super for U with T <: U exists. Nothing is inherited — add the missing supertrait impl.
OE0675ErrorLiveSelfMisuseSelf is used outside the positions where it resolves. Self resolves only inside trait and impl bodies: in a trait member signature it is the obligation’s type parameter; in an impl member it denotes the impl’s target type. The full discipline: (1) Self outside a trait/impl body never resolves — it is not a module-level type; (2) a trait member signature must mention Self in at least one parameter position (a member that is not about the implementing type belongs at module level); (3) return-position Self on a query member is refused — it would make the dispatch endpoint’s type a union over impl targets, which needs union types or bounded generics (V1). Move the declaration into a trait/impl body, or replace Self with the concrete declared type.
OE0676ErrorLiveImplMemberSeverityDivergesAn impl’s check member states a severity different from the one its trait pins. A trait-side check member signature may pin its severity (check OverLimit(Self) => Severity::Error;); the pin makes the member’s blocking behavior part of the trait contract — a contract whose blocking behavior varies by implementor is a weak contract (an Error that guards mutations on one target but merely warns on another is not one obligation, it is two). Under a pin an impl may omit its payload’s severity: field (it inherits the pinned one — the ergonomic point of pinning) or restate the same severity (harmless); stating a different one is refused here, naming the trait, the member, the pinned severity, and the divergent one. Codes and messages stay per-impl. To keep per-impl severity freedom, remove the pin from the trait signature.

Modules, attributes, temporal, modal, forget (07xx)

CodeSeverityStatusNameMeaning
OE0701ErrorReservedInvertedDurationMetric temporal operator declared with bounds [a, b] where a > b (§7.3.2).
OE0702ErrorReservedMetricArityMismatchUnary metric temporal operator applied to two operands (or binary applied to one) (§7.3.2).
OE0703ErrorReservedMetricAtomBelowTierMetric temporal atom appears under temporal: snapshot or temporal: none (§6.10.5).
OE0704ErrorLiveReservedIntrinsicNameA declaration is named after an IDENT-lexed reflection intrinsic (implements, implementors, spec §4.4). Rule-body call forms of these names always denote the intrinsic, so the declaration would be silently unreachable. Rename the declaration. The keyword intrinsics (iof, specializes, meta, extent) cannot collide and need no gate.
OE0705ErrorLiveUnknownDirectiveAn #[...] attribute names no registered compiler directive (the directive registry). Unknown attributes never silently no-op: a typo’d directive (#[defeasable]) would otherwise silently change rule semantics — the canonical case let a felon vote. The diagnostic suggests the nearest registered directive when one is within typo distance. Macro-invocation attributes (spec section 13) are not built; until they are, every attribute must be a registered directive.
OE0706ErrorLiveDirectiveReservedUnimplementedA directive the book documents but the toolchain does not implement (#[brave], #[intrinsic], #[coinductive], …). Refused loudly rather than silently ignored: a directive that parses green while doing nothing misrepresents program semantics. The message cites where the directive is documented and what to do instead. (Removed surfaces — the #[strict]/#[defeasible]/#[defeater] strength triple and #[priority] — refuse under OE0722 instead, with a migration hint.)
OE0707ErrorLiveDirectiveInvalidPositionA registered, executed directive attached to a declaration kind it does not apply to (e.g. #[static] on a derive rule, #[comptime] on a mutate). Previously ignored silently; the registry names the directive and its valid positions.
OE0708ErrorReservedReservedAttributeNameA user pub macro or #[procmacro] pub fn declaration shadows a compiler-reserved attribute name (§9.2).
OE0709ErrorLiveAttributeArgsNotYetImplementedAttribute argument form not yet implemented; only the bare form is admitted (e.g. #[comptime], not #[comptime(strict)]). The argument syntax is parser-reserved for a future release.
OE0710ErrorReservedModuleExtractionConservativityViolationModule extractor cannot prove conservativity under the importing module’s world assumption (§3.5).
OE0711ErrorReservedModuleExtractionDefeatChainBrokenDefeat-aware extraction cannot close the defeat graph — a referenced defeater is excluded by the seed signature (§3.5).
OE0712ErrorReservedModalTemporalCrossNestRefusedModal operator nests a metric temporal operator (or vice versa) at tier: recursive. Route to tier: fol (§9.1).
OE0714ErrorReservedDirectiveConflictTwo directives from one mutually-exclusive family on a single declaration. Its only family was the rule-strength triple #[strict] / #[defeasible] / #[defeater], removed — each member now refuses individually as removed (OE0722), so a conflict never forms and this code has no live emitter. Reserved for a future exclusive-directive family rather than reused (registry hygiene).
OE0715ErrorLiveModuleHeaderReadingRemovedA content-carrying file declares mod NAME; (no sibling NAME.ar, no inline { … } body) in the legacy module-header position — the reading where the mod renamed the file’s OWN namespace. mod NAME; has a single meaning, Rust’s: it declares a CHILD module backed by a sibling NAME.ar (or NAME/mod.ar). A file cannot rename itself. Refused loudly: the silent-rename meant a typo’d mod quietly relocated a whole file’s declarations under a phantom namespace while ox check stayed green. To name a package’s module, use the directory/file layout (the root file is module root); to declare a child module, create the sibling NAME.ar; to keep declarations at the current namespace, delete the mod NAME; line.
OE0716ErrorLiveDefeatTargetUnresolvableA #[defeats(target(args))] target resolves to nothing: no derive head of that name, no clause carrying that #[label], or no trait member at that @ Type impl in the module. Defeat targets are resolution-checked at elaboration (goto-def-able) so a typo never silently changes which norm a program concludes. Also covers a malformed call-form target and a bare #[defeats] with no target. The accepted forms are head(args), head.label(args), and Trait::member(args) @ Type.
OE0717ErrorLiveDefeatsStrictConclusionA #[defeats(...)] target resolves to a head/clause not marked #[default]. Strict conclusions are unattackable: adding rules to a classical program can only add conclusions, and defeat exists only where overridability was declared. Mark the targeted clause #[default] to make it overridable, or remove the attack.
OE0718ErrorLiveDefeatGraphCycleThe defeat graph (over resolved rule identities — clauses and heads) has a cycle, refused in v1. Cyclic attack structures are exactly where the well-behaved compilation stories diverge; v1 refuses rather than picking one silently. An exception-to-an-exception (a #[default] rule that is itself a #[defeats] target) is legal as long as the chain bottoms out. The message names the cycle rule by rule.
OE0719ErrorLiveDuplicateClauseLabelTwo clauses of one head carry the same #[label(name)]. Labels are per-head identities — head.label must address exactly one clause — so a head cannot have two clauses labeled alike. Rename one of the labels.
OE0720ErrorReservedNonUniformBridgeRefusedBridge consults facts at a different valid-time than the bridge head’s; refused outside tier: fol (§10.3).
OE0721ErrorLiveDefeatArgumentUnboundA #[defeats] target argument binds in neither the head nor the body of the decorated rule, or binds only in the body (per-tuple defeat keys on the attacker’s HEAD tuple). A directive argument is never a fresh variable — the lesson that a silently-fresh variable matched everything. Name a variable the attacker derives in its head.
OE0722ErrorLiveDeprecatedStrengthAttributeThe Governatori strength-attribute surface — #[strict] / #[defeasible] / #[defeater] and #[priority] / pub priority — is removed. It silently inverted a head’s polarity at a distance (a defeater spelled the head it denied) and numeric priority was non-compositional and silently dropped. The replacement is honest heads plus the defeat-directive plane: unmarked rules stay strict; #[default] marks an overridable clause; an exception is an ordinary rule under its own honest head carrying #[defeats(target(args))]; lex specialis is the specific rule defeating the general clause’s #[label]. No silent aliasing — migrate the program. The help text shows the new form for the specific attribute.
OE0723ErrorLiveMacroInvocationDidNotExpandA macro invocation name!( … ) survived the EXPAND phase: no pub macro name with a rule matching the invocation is in scope (the macro is undefined in this module, or none of its rules’ matchers bind these arguments). An unexpanded invocation is refused rather than silently accepted — an invocation the elaborator does not understand must not vanish from the artifact (the silent-wrong discipline forbids). Define the macro, fix the invocation to match a rule, or import the macro (cross-module macro use is a follow-up).
OE0724ErrorLiveUnknownFragmentSpecifierA macro metavariable $name:spec names a fragment specifier outside the closed v1 set. The admitted specifiers are the ontological concept / rel / metatype / rule and the syntactic expr / ident / ty / literal / path / tt; standpoint is cut from v1. Validated at expansion so a macro body never binds a metavariable against a parse category the expander cannot honor. Use one of the admitted specifiers.
OE0725ErrorLiveReservedHygieneIdentifierA user-authored identifier contains the reserved hygiene marker · (U+00B7 MIDDLE DOT). That marker is reserved for the names macro hygiene mints when freshening a macro-introduced variable, giving those names a namespace provably disjoint from anything a user can write — the disjointness the hygiene non-capture guarantee rests on. Remove the · from the identifier.
OE0726ErrorLiveDuplicateMacroDefinitionA module declares two macros with the same name. A macro name must have exactly one implementation per module (uniqueness-at-registration) — two macro name { … } declarations are a loud error, never a silent merge or shadow (the silent-wrong discipline forbids; the two rule sets would otherwise be invoked as if one macro). Rename or remove one of the declarations; a distinct cross-module macro of the same name is reached with a module-qualified use.
OE0727ErrorLiveMacroExpansionDidNotConvergeA module’s macro expansion did not reach a fixed point within the fuel budget: a macro whose expansion re-introduces an invocation of itself (directly or through a cycle) diverges. The phase stops and refuses rather than looping forever — distinct from OE0723 (an invocation that no rule matches), since here the macro does match but its expansion never settles. Break the recursion (add a non-recursive base rule, or stop the rule from re-emitting its own invocation).
OE0728ErrorLiveExpansionSpanUnanchoredA diagnostic produced over macro-expanded text carried a span that the source-faithful expansion provenance map could not resolve to any location the user wrote. This is a compiler bug: every span over expanded input must resolve to real user source (a copied-through fragment) or to the invocation site of the macro that synthesized it. The compiler refuses to render text the user never wrote, so it surfaces this internal error loudly rather than pointing at a phantom location. Please report it with the input that triggered it.
OE0729ErrorLiveProcmacroBodyNotTotalA procedural macro (#[procmacro] pub fn) body uses a construct outside the total fragment, so its termination cannot be guaranteed by construction. The procedural meta-language is deliberately a closed, strongly-normalizing fragment: let bindings over string literals / reflection projections (item.name, item.params[i].ty) / concat_idents(…) paste, a quote { … } (with $-splices and a bounded $( for x in item.fields ) { … } repetition over a reflected child-list), and a list of quote/typed-artifact elements. General control flow (if / match / for / while statements) and calls to anything other than concat_idents are refused HERE, at the declaration — totality is enforced, not trusted to a fuel cap at expansion time (distinct from OE0727, which catches a runaway at expansion). Rewrite the body within the total fragment; iteration over a declaration’s structural children is the bounded $( for … ) repetition inside quote, not an open loop.
OE0730ErrorLiveForgetWithoutCapabilityA mutate body contains forget but the enclosing mutate declaration does not grant #[allow_forget]. forget physically erases axiom events including their bitemporal history; the capability must be granted explicitly at the declaration that wields it. The richer capability plane (ox.toml / backend principal / _forget_log audit) is a recorded follow-on.
OE0731ErrorReservedForgetLogTamperAttempted forget on a _forget_log event.
OE0732ErrorReservedRetentionViolationQuery targets transaction-time outside the declared #[retention(tx_time, ...)] window.
OE0733ErrorLiveSchemaDeclInStandpointA schema-level or rule/invocation declaration appears inside a standpoint { … } block. The refused forms are the vocabulary declarations (pub type / pub rel / metaxis / metatype / metarel / enum / struct) AND the rule/invocation forms (derive / check / query / mutate / bridge / fn / trait / sink / macro); only pub fact / pub not_fact (and mod / use / test / a nested standpoint) are admitted. A standpoint contributes a SOURCE’S VIEW of ground truth — facts — not the universe’s vocabulary or its rule/invocation/derivation logic; those describe the universe and belong at module level. The elaborator silently DROPPED these (the decl vanished from the artifact: pub query against a standpoint-nested type then failed unresolved type, proving it never existed), while the checker half-saw them (it reference-checked a standpoint-nested rel against a sibling decl it could not see, mis-reporting unresolved type for a type sitting two lines above) — a silent drop plus a check/lowering split-brain. Refused at ox check / ox build, parallel to the impl-in-standpoint refusal added to the same dispatch. Move the schema declaration to module level; only facts are standpoint-scoped. (Per-standpoint schema scoping is a recorded open design question, not a v0 feature.)
OE0734ErrorLiveProcmacroSignatureTypeA procedural macro (#[procmacro] pub fn) signature names a type outside the reflection vocabulary. A procmacro is a macro definition, not a value-level function: its parameters reflect the macro’s input — Decl (the decorated declaration), Args (the attribute arguments), or Syntax (a function-like macro’s token input) — and it returns Syntax (a single emission) or Expansion (a list of emissions / typed artifacts). These reflection types are the only ones admitted in a procmacro signature; an ordinary value type (or a typo) is refused here so the macro author is not silently handed a meaningless signature. Use one of the reflection types.
OW0710WarningReservedOrphanModuleFileReserved (no emitter): an .ar file under the package source root reached by no mod/use chain from the entry is not part of the package (Rust module semantics, §3.1) — not compiled, not checked, not linted. Argon matches Cargo and says NOTHING about such a file: an unreferenced source file is simply not compiled, not surfaced as a warning. The orphan set is still computed (the workspace records it; a future tool may surface it as an editor hint), so the code is held rather than retired. Declare the file with a mod item from a reachable module to include it.

Field modifiers, world-assumption gates, construction (08xx)

CodeSeverityStatusNameMeaning
OE0810ErrorReservedWorldAssumptionTemporalIndex#[world(...)] declared per concept with a valid-time scope but no standpoint context (§6.9).
OE0811ErrorReservedPersistenceMarkerOnNonTemporalRulePersistence marker applied to a rule outside the temporal substrate.
OE0812ErrorReservedDefeasibleDefeaterOfDefeasibleTemporalDefeasible defeater of a defeasible temporal rule; route to unsafe logic (§7.8).
OE0820ErrorLiveUpdateImmutableFieldAn update target: T set { f = … } writes to a field f that T declares without the mut modifier. The elaborator validates each field-assignment against the field-decl’s mut flag and refuses at build time, not at mutation invocation. Emitted by the mutate-body lowerer (oxc-instantiate); a bare (un-annotated) target defers to the runtime rather than emitting here.
OE0822ErrorReservedMutOnDerivedFieldReserved (designed — §5.1): a mut modifier on a from-navigation-derived field, which is contradictory — a derived field has no independent value to mutate. mut is otherwise orthogonal to the other field-decl modifiers (#[intrinsic], defaults, metatype rigidity). This entry reserves the code for that gate.
OE0831ErrorLivePositionalInsertArityMismatchA positional insert C(a, b, …) targets a concept C. The mutate-body lowerer only routes the brace form insert C { field: … } to construction, so a positional concept insert silently constructs nothing; it is refused at check. The diagnostic names the required fields in constructor order and (on an arity mismatch) reports the argument-vs-field counts. Emitted by the driver’s mutate-body validation (oxc-driver). Use the brace form insert C { field: … } to supply fields by name.

World-assumption conservativity (09xx)

Reserved range — the §6.9 world-assumption gates are designed but not yet wired.

CodeSeverityStatusNameMeaning
OE0901ErrorLiveMixedWorldAssumptionConflictA rule or query applies negation-as-failure (not R(..)) to a FOREIGN relation (one mapped to a store by [placement.R]) whose source is read open-world — the CWA-importing-OWA boundary. A foreign relation is materialized into the fixpoint as a frozen CLOSED-world slice (the frozen-EDB rule), so not R(..) reads absence-in-the-slice as definite-false; but absence of a tuple in an OPEN-world source is UNKNOWN, not false (§6.9), so the negation reads unknown as definitely-false and over-asserts its head. The closed-world lifting of the slice into the open consumer is not provable — the TypeSystem/Soundness/CwaOwa.lean conservativity theorem proves the CWA→OWA transfer sound in one direction only — so the negation is refused at ox check / ox build rather than silently evaluated, the C6×D4 hinge (a CWA relation admits NAF; an OWA one does not). To resolve: mark the relation’s source closed-world (so absence IS falsity and not R is sound), or restructure so the foreign relation is not negated. The native-concept analog — NAF over a #[world(open)] concept’s own derived extent — is the separate OE1367 gate (the evaluator threads it three-valued); this code is the federation boundary, where the frozen slice is a closed snapshot of an open source.
OE0903ErrorReservedWorldAttributeOnStructReserved — superseded by OE0707: #[world(...)] applied to a struct/enum, which carry no ontological classification — world assumption applies only to classified concepts. The world directive is now registered concept-only (positions: [CONCEPT_DECL]), so a struct/enum placement refuses via the generic placement gate OE0707; this bespoke code is retained as a reserved row and does not fire.
OW0902WarningReservedWorldAssumptionImplicitReserved (designed — §6.9): default_world omitted from ox.toml, so the substrate applied a default world assumption rather than an explicit modeler choice. The warning that would suggest making the choice explicit is unbuilt; this entry reserves the code.

CWA evaluation and field intent (10xx)

CodeSeverityStatusNameMeaning
OE1014ErrorLiveRequiredFieldUnassertedUnder the closed-world default (book §6.9 — CWA everywhere today), a required field’s value is not derivable from any asserted axiom: the schema declares the field present but the KB does not assert it. Emitted by the runtime mutate path (oxc-runtime) at exactly one site: the in-body insert iof(x, T) construction-completeness gate — classifying x into T whose required fields x lacks, when the same body also populates fields of x, refuses atomically, judged at body end so insert iof; update set { … } in one mutation is complete (read-your-writes). Distinct from brace construction (insert T { … } missing a field → OE0207). Staged construction (classify in one mutation, populate later — no in-body field writes) currently emits NO diagnostic: the absent required field reads as K3-unknown and collapses to CWA-false at access. The field-access-time / evaluation-channel emitter that would surface staged incompleteness is designed and is not built in v0. #[world(open)] is a live concept attribute; the permit-as-unknown softening of this required-field gate under an open-world concept is designed and not yet wired.
OE1016ErrorReservedTruth4OfOnStructTruth4Of<T> field type appears on a struct (no metatype classification). The four-valued surface is restricted to metatype-classified concepts (pub type ..., or a declared vocabulary introducer).
OW1015WarningReservedOptionalFieldAmbiguousIntentReserved (no emitter): an optional field field: T? does not record whether its optionality is structural (the value may legitimately be absent) or epistemic (the value exists but is unknown), a distinction drawn from JPA’s TBox/SHACL split. The intent-marking surface and the warning that would request it are unbuilt — the #[intent(...)] attribute does not exist yet (the lint-level #[allow(...)] / [lints] suppression surface does, and this code is wired to the optional-field-ambiguous-intent lint, so the warning will be suppressible the moment it gains an emitter). This entry reserves the code for that future surface; today every T? field checks clean.

Bridges (11xx)

CodeSeverityStatusNameMeaning
OE1101ErrorReservedBridgeCycleThe bridge graph (nodes = standpoints, edges = bridges) contains a cycle that prevents stratified evaluation. Cycles between standpoints under bridge composition would require fixed-point recomputation across the federation; v0.1 admits only acyclic bridge graphs. Either break the cycle (drop one of the bridges) or wait for the V1 #[managed] bridge surface (spec §10.3).
OE1102ErrorLiveBridgeNotEvaluatedA pub bridge declaration (§10.3). Bridge rules parse, lower to BridgeDecl wire events, and resolve, but the federation fixpoint never fires them (Module::bridges_targeting has no callers) — a built artifact’s bridge bodies would silently never contribute to their target standpoint. Refused at ox check / ox build rather than building an artifact whose declared inference is inert. Bridge evaluation is the post-stable flagship standpoint deliverable; the parse / lower / wire / decode surface is retained so the work resumes without a grammar or wire-format change. Model the cross-standpoint inference with an explicit derive / pub fact for now.
OE1103ErrorLiveUndeclaredStandpointInAcrossA pub query … across [ … ] clause names a standpoint that is not declared in the workspace. Under the standpoint visibility composition rule (§10.4), a federated query reads the named standpoints’ views info-joined with the DEFAULT layer; a name that resolves to no standpoint declaration would silently contribute the DEFAULT layer alone (an empty per-standpoint extent), masking the typo as a real — but wrong — federation result. The query is refused loudly at dispatch naming the unknown standpoint. Declare the standpoint, or correct the name in the across clause. Mechanization: Argon.Visibility (the visibility relation the federated materializer honors).

Build composition and .oxbin validation (12xx, §16)

CodeSeverityStatusNameMeaning
OE1201ErrorLiveInvalidMagic.oxbin magic header does not match \0oxbin\0\1.
OE1202ErrorLiveIncompatibleVersionAxisMajor bump on one of the four version axes (oxbin_format_version, core_ir_version, tier_ladder_version, runtime_contract_version).
OE1203ErrorLiveUnknownMandatorySection.oxbin carries a MANDATORY-flagged section type the runtime does not recognize.
OE1204ErrorLiveTierMismatchArtifact’s max_tier_claimed or max_temporal_claimed exceeds the runtime’s supported maxima.
OE1205ErrorLiveArrangementSectionUnsupportedMVP runtime refuses an .oxbin carrying a DBSP-shape arrangement-section.
OE1210ErrorLiveSymbolResolutionFailedLayer-2 validation: a reference in events / rules / queries / mutations did not resolve to a symbol-table entry.
OE1211ErrorLiveStandpointLatticeCycleStandpoint lattice has a cycle (compose-time or load-time).
OE1212ErrorLiveProvenanceNotDNFAn event’s derivation column is not a well-formed PosBool(M) DNF.
OE1213ErrorLiveCompositionSignatureMismatchStored composition_signature does not match what its four legs compute.
OE1214ErrorLiveTierTableInconsistentA rule’s tier in tier-table exceeds the artifact’s max_tier_claimed.
OE1215ErrorLiveDocLinkUnresolvedA DocBlock cross-link does not resolve; strict policy fails, lenient warns.
OE1220ErrorLiveUnknownAxiomKindEvents section carries a variant tag the runtime does not recognize.
OE1230ErrorLiveTierCapExceededCompose-time: a declaration’s classified decidability tier exceeds the workspace ceiling set by [lattice].max_tier in ox.toml (§10). The ceiling is the highest of the seven ladder tiers (structural, closure, expressive, recursive, fol, modal, metaorder) a package admits; a rule the §10 classifier places above it is refused at ox check/ox build rather than emitted into an artifact that claims a tier it exceeds. Raise max_tier, or rephrase the declaration into the admitted fragment.
OE1240ErrorLiveDependencyVersionUnsupportedAn ox.toml [dependencies] entry uses a registry/VCS form — a bare version string (dep = "1.0") or one of the version/git/branch/tag/rev/registry keys — that is not yet supported. v1 supports path dependencies only (dep = { path = "../dep" }). The form is recognized and refused feature-named, not silently ignored: a version requirement that silently resolved to nothing (or to a path) would be silent-wrong. Use a path dependency, or wait for the registry story.
OE1241ErrorLiveDependencyNameMismatchAn ox.toml [dependencies] key does not match the [package].name of the package at the declared path. The dependency name is the path root the consumer uses (use dep::X;, dep::X), and v1 keeps the dependency’s published name authoritative (Cargo’s default). Rename the [dependencies] key to the package’s published name, or fix the path.
OE1242ErrorLiveDependencyCycleThe [dependencies] graph contains a cycle. Package dependencies must form a DAG; a cycle is refused loudly naming the cycle path (a -> b -> a). Break the cycle — extract the shared surface into a third package both depend on.
OE1243ErrorLiveDuplicateDependencyNameA dependency name collides as a path-resolution root: either the same name resolves to two different package directories across the dependency graph, or it equals an intra-package top-level module name. A name is a single namespace root; it cannot denote two things, and a bare name::X must not silently prefer one. (Two declarations resolving to the SAME canonical directory are de-duplicated, not an error.) Rename the conflicting dependency or the local module.
OE1244ErrorLiveDependencyPackageLoadFailedA path dependency could not be loaded: the path does not point at a directory with an ox.toml, the dependency’s entry/module closure failed to resolve, or its manifest did not parse. The dependency is refused naming the path and the underlying cause rather than silently contributing nothing.
OE1245ErrorLiveMappingSchemaDriftA compiled placement/mapping artifact pins to a Schema composition signature that does not match the schema it is being loaded against. The mapping compiles to a content-addressed artifact hashed against the schema’s composition signature, so a schema change that the mapping was not recompiled against is a LOAD-TIME refusal rather than a runtime surprise: a relation could otherwise be mapped to a store under a shape the schema no longer has. Placement is versioned separately from the schema — a relation can move stores without a schema bump — but the mapping always pins to the schema hash it was compiled against. Recompile the mapping against the current schema (ox build).
OE1246ErrorLiveForeignRelationAlsoDerivedA relation is BOTH mapped to a foreign store by a [placement.<rel>] section AND produced by a derive rule. A relation’s extent must have a single origin — it is EITHER extensional (its rows live in the foreign store the placement points at) OR intensional (its rows are computed by rule derivation) — never both. Allowing both would silently produce an ambiguous extent: the foreign rows and the derived rows would compete, and which one a query reads would depend on evaluation order rather than on the model. The conflict is refused at build time naming the relation, rather than emitting an .oxbin whose foreign-vs-derived extent is undefined. Either drop the derive rule (the relation is foreign-owned) or remove the [placement] (the relation is rule-computed).
OE1247ErrorReservedConflictingPlacementReserved (designed, not yet wired): a relation has a placement declared from two sources at once — e.g. an ox.toml [placement.<rel>] section AND a source-level foreign!/#[foreign] macro, or the same relation placed twice. A relation may be bound to at most one store; two placements would compete for which store backs the relation’s extent, and which one wins would depend on merge order rather than the model. The placements are unioned at build time (MappingSections::merge_placements) and a relation appearing in more than one source is refused, naming the relation, rather than silently overwriting one with the other. The union seam exists; the build path that emits this code on a macro-emitted-vs-config collision is wired when the macro emission surface lands. Keep a single placement for the relation — either the ox.toml section or the macro, not both.
OE1248ErrorLiveWorkspaceInheritanceUnavailableA [package] field uses the workspace-inheritance form { workspace = … } but there is no enclosing [workspace] to inherit from, or the value is workspace = false. Per-field inheritance (version.workspace = true, edition.workspace = true) is meaningful only for a member of a workspace whose root declares the shared [workspace.package] field. Set workspace = true inside a real workspace, or write the value literally.
OE1249ErrorReservedUnknownEditionReserved (no emitter) — edition-value validation deferred until editions gate surface syntax. Editions are non-negative integers, opt-in per package, parse-time-only and inert in v1: the resolved value gates nothing downstream, so any integer (given as edition = 1 or the legacy string edition = "1") is accepted. This code is held so that once an edition gates real surface syntax, an edition this toolchain does not understand can be refused feature-named rather than silently treated as the default.
OE1250ErrorLiveWorkspaceMemberVersionUnsatisfiedA workspace member depends on a sibling member (or a path dependency) whose declared [package].version does not satisfy the depending package’s SemVer constraint. A member-to-member dependency resolves LOCALLY to the sibling member directory — never to a registry — so the sibling’s declared version must satisfy the constraint, or the workspace is internally inconsistent. Align the member version, or relax the constraint.
OE1251ErrorLivePatchTargetUnsupportedA root-only [patch.<source>] entry targets a registry/VCS source that is not yet supported. v1 patches only path/workspace sources; a registry patch is refused feature-named rather than silently ignored, since the registry does not yet exist. Patch a path/workspace source, or wait for the registry story.
OE1252ErrorLiveWorkspaceMemberGlobEmptyA [workspace] members glob matched no package directory. A member glob must resolve to at least one directory holding an ox.toml; an empty glob is refused rather than silently producing a member-less workspace (a typo in members = ["crates/*"] would otherwise drop every member without a word). Fix the glob, or remove it.
OE1253ErrorLiveWorkspaceMemberGlobMalformedA [workspace] members/exclude/default-members glob is malformed: an invalid glob pattern, or an unreadable matched path. The pattern is refused naming the glob and the underlying cause rather than silently expanding to nothing.
OE1254ErrorLiveWorkspaceInheritedFieldMissingA workspace member inherits a field with <field>.workspace = true (or <dep>.workspace = true) but the workspace root’s [workspace.package] / [workspace.dependencies] does not declare that field. Inheritance pulls the shared declaration from the workspace root; if the root does not declare it, there is nothing to inherit. Declare the field under [workspace.package] / [workspace.dependencies], or give the member a literal value.
OE1255ErrorLiveWorkspaceDependencyOverrideA workspace member inheriting a dependency with <dep>.workspace = true overrides a field of the inherited [workspace.dependencies] declaration beyond what is permitted. A member may add only optional / features over the inherited declaration (additive); it may not redeclare the source (path/version/git/…). Drop the override, or stop inheriting and declare the dependency in full.
OE1256ErrorLiveWorkspaceDefaultMembersEmptyA [workspace] default-members list resolved to no package directory. A declared default-members must name at least one existing member; a list that matches nothing is refused rather than silently building an empty default set (a typo would otherwise drop every member without a word). Fix the default-members entries, or remove the key to default to all members.
OE1260ErrorLiveLockfileMalformedAn ox.lock lockfile failed to parse. The lockfile is the machine-generated record of the resolved package graph; a hand-edited or truncated lock is refused naming the parse cause rather than silently regenerated, since silently overwriting a corrupt lock would hide a merge conflict or a botched edit. Delete the lock to regenerate it (ox build), or fix the malformed entry. The lockfile is auto-generated — do not edit it by hand.
OE1261ErrorLiveLockfileContentHashMismatchA package’s recomputed content_hash does not match the value recorded in ox.lock. The lock pins each resolved package to a deterministic BLAKE3 hash over its source (the .ar files plus a normalized ox.toml); a mismatch means the on-disk source changed under a committed lock. Outside --locked/--frozen the lock is refreshed automatically on the next resolve; under --locked/--frozen it is a loud refusal, because a CI build must not silently build different source than the lock pins. Re-run without --locked to refresh the lock, or restore the pinned source.
OE1262ErrorLiveLockfileDriftThe resolved package graph does not match the committed ox.lock under --locked/--frozen: a package was added, removed, or its version/source/content_hash changed since the lock was generated. --locked requires the lock to already describe the resolution exactly and refuses to regenerate it, so drift is a loud refusal rather than a silent rewrite — the strict-CI contract that the build matches the committed lock. Re-run without --locked to update the lock, then commit the updated ox.lock.
OE1263ErrorLiveLockfileMissingNo ox.lock exists at the workspace root, but --locked/--frozen was requested. These flags require a committed lockfile to verify the resolution against; in their absence there is nothing to honor, and silently generating one would defeat the strict-CI guarantee that the build matches a reviewed lock. Run ox build (or ox check) without --locked once to generate and commit ox.lock, then re-run with the flag.
OE1264ErrorLiveUnresolvableDependencyGraphThe dependency graph has no solution: there is no single assignment of one version per package that satisfies every requirement. Argon resolves each package name to EXACTLY ONE version graph-wide — unlike Cargo, it never lets two semver-incompatible versions of the same package coexist under name-mangling, because two concepts at one qualified path cannot both be ‘the’ type (the nominal-identity invariant). So two requirements that pin the same package name to disjoint version ranges are an unsatisfiable conflict, refused loudly rather than silently mangled into coexistence. The diagnostic carries the PubGrub derivation chain — the root-cause sequence of ‘because A depends on B and C requires not-B’ steps that proves no solution exists. Relax a version constraint, align the conflicting requirements on a shared version, or drop one of the conflicting dependencies.
OE1265ErrorLiveRegistryFetchFailedA registry read failed: a transport/network error, an unreadable file:// index path, a malformed index record, or an offline build with no warm cache entry. The registry is a static content-addressed store (a config.json plus an append-only NDJSON sparse index over https:///file://); a read that cannot answer is refused loudly rather than treated as an empty result, because a silently-empty index would resolve a real dependency to nothing (silent-wrong). Check the registry URL/path is reachable, or build --offline against a warm cache.
OE1266ErrorLiveRegistryContentHashMismatchA fetched package artifact’s BLAKE3 hash does not match the cksum the registry index recorded. The content hash is the artifact’s content-address: a mismatch means the artifact is corrupt, truncated, or tampered. This is a FAIL-CLOSED refusal — the artifact is never cached or built, so a bad registry object cannot enter the build. Re-fetch; if the mismatch persists the published object is bad. (Cryptographic signatures over the artifact are out of scope; v1 integrity is the content hash only.)
OE1267ErrorLiveNoRegistryConfiguredA registry dependency is declared but no registry is configured. A bare version requirement (dep = "1.0") or a { version = "1.0" } form that names no local workspace member is a REGISTRY dependency — it resolves against a configured sparse index. This REPLACES the old OE1240 ‘registry form reserved for later’ refusal: the form is supported now, it just needs an index. Add a [registry] table to ox.toml (index = "file:///path" or index = "https://…"), or set ARGON_REGISTRY; to depend on a local checkout instead, use a path dependency (dep = { path = "../dep" }).
OE1268ErrorLiveRegistryPackageNotFoundThe package — or a version satisfying the requirement — is not in the registry index. The sparse index has no record file for the package name, or the version requirement matches no published version. Refused loudly rather than resolved to nothing. Check the package name and the version requirement, and that the package has been published to this registry.
OE1269ErrorLiveRegistryYankedVersionSelectedThe only version satisfying the requirement is yanked, and the requirement is not an exact pin. A yanked version is withdrawn from new resolutions — it stays selectable only when pinned exactly (= x.y.z), e.g. from an existing ox.lock that already pinned it, so a yank never breaks a locked build but is not picked for a fresh resolve. Pick a non-yanked version, or pin exactly if you must depend on the yanked one.
OE1270ErrorLiveRegistryArtifactTooLargeA registry body (an index record or a package artifact) exceeds the transport’s hard size cap. A registry read buffers the whole body before its content hash can be checked (OE1266 only protects AFTER the body is in memory), so an unbounded body is a denial-of-service: a malicious or buggy registry can exhaust memory or hang the build on a slow drip. The cap (a build-time constant, 256 MiB — far above any plausible published SOURCE package) is a hard refusal, not a truncation, and is enforced both before the download (when the index declares a size over the cap) and during it (the read itself is bounded); the server’s Content-Length is never trusted. If a package is legitimately this large, the cap must be raised deliberately.
OE1271ErrorLiveRegistryInvalidPackageNameA registry dependency name is not a valid package identifier. A package name is used VERBATIM as a filesystem path segment — the index shard path and the content-addressed cache path under ~/.argon — so it must match [A-Za-z0-9_-]+ (non-empty, ASCII alphanumerics plus _ and -): no path separators, no ./.. components, no empty string. A name like ../../tmp/x would otherwise escape the cache root and write outside it; this is validated at the manifest boundary, before the name reaches any path join, and refused loudly rather than silently traversing. Fix the dependency name in ox.toml.
OE1272ErrorLivePublishManifestInvalidox publish refused because the package manifest is not publishable. A published package’s ox.toml must declare a [package] table with a non-empty name matching the registry charset [A-Za-z0-9_-]+ and a parseable [package].version — the index keys a version record by exactly that (name, version). A missing/empty name, a name with a path separator or .. (which would escape the index shard / cache path), or an absent version is refused loudly rather than published under a guessed coordinate. Fix [package] in ox.toml.
OE1273ErrorLivePublishVersionExistsox publish refused because <name>@<version> is already published to this registry. The sparse index is APPEND-ONLY and every published artifact is immutable (content-addressed): a version is published exactly once and never overwritten, so a re-publish of the same coordinate — which would silently change what a downstream lock already pinned — is a hard refusal, not an in-place mutation. Bump [package].version and publish the new version; to withdraw a bad version use a yank (an append-only event), never an overwrite.
OE1274ErrorLivePublishRegistryWriteFailedox publish could not write to the target registry. v1 publishes to a LOCAL / file:// registry only — it writes the content-addressed blob under blobs/, appends the version record to the package’s NDJSON index shard, and ensures config.json — so the target must be a writable local directory or file:// URL. Publishing to an https:// production CDN registry needs upload + auth and is out of scope for v1. Check the registry path is a writable local directory, or point --registry / [registry].index at a file:// path.
OE1275ErrorLivePublishEmptyPackageox publish refused because the package has no publishable source. A package directory must hold an ox.toml and at least one .ar source file — an empty package (no .ar files), or a path that is not an Argon package directory at all, is refused loudly rather than publishing an empty artifact that would resolve to nothing downstream. Add source, or publish the correct package directory.
OE1276ErrorLivePublishBreakingChangeox publish refused because the new version makes a BREAKING change to its pub declaration surface without the breaking-tier SemVer bump. Argon recomputes the constructs semantic signature of both the version being published and the latest previously-published version of the same package, diffs them per declaration, and classifies each change against the compatibility taxonomy — proven sound in the scratch-Lean oracle (binary-compatibility, JLS Ch.13 analog): a COMPATIBLE change (a new pub decl, a widened bound/refinement, grown <: parents, widened cardinality) may publish as a patch, but a BREAKING change (removing/renaming a pub decl, narrowing a refinement — including adding a not P (NAF) clause —, an arity / position-type change, narrowing cardinality, or a not-clause-bearing closed→open (CWA→OWA) world flip) requires the breaking tier: a MAJOR bump in 1.x+, a MINOR bump in 0.x (Cargo’s 0.MINOR.PATCH rule — a 0.MINOR bump is the breaking tier pre-1.0). This is refused loudly, naming the offending declaration(s), the kind of break, and the required bump, rather than silently publishing a version a downstream ^-range would auto-adopt and then fail to resolve/check against. Bump [package].version to the required tier, or make the change compatible. The first-ever publish of a package (no prior version) is unconstrained.
OW1240WarningLiveUnusedManifestKeyAn ox.toml section or key is not recognized by the compiler (Cargo-style “unused manifest key”). Recognized surface is [package]/[project]/[schema]/[dependencies]/[lattice]/[standpoints]/[store]/[placement]/[workspace]/[patch]/[registry]/[fmt]/[lints] and their known keys; anything else (a typo, a not-yet-supported section, an unknown [lattice].max_tier ladder name) is surfaced as a warning naming the section/key rather than silently dropped by deserialization.
OW1241WarningLiveUnknownLintA lint name in a #[allow/warn/deny(...)] attribute or the ox.toml [lints] table is not a registered lint. A lint name keys a level-controllable diagnostic (e.g. non-canonical-clause-order for OW0010); an unknown name is surfaced — with a did-you-mean suggestion when one is close — rather than silently ignored, because a typo’d name would leave the diagnostic at its default level with no signal. The level value itself (allow/warn/deny) is also checked: a [lints] entry whose value is not one of those words is reported here too. The configured lint set is OxcDiagnosticCode::ALL_LINTS.

Runtime contract and rule-evaluation gates (13xx, §17)

ox build is fail-closed: it re-runs the runtime’s own rule compiler as an oracle over every rule and refuses to write an .oxbin if any rule will not evaluate. The aggregate/quantifier codes (OE1311–OE1315) are the gate’s refusals.

CodeSeverityStatusNameMeaning
OE1301ErrorReservedUnsafeLogicTimeoutQuery touching an unsafe logic { } rule exceeded the runtime’s wall-clock budget (§17.5).
OE1302ErrorReservedFederationDisagreementA federated query under #[federate(strict)] produced a row whose AFT info-join across contributing standpoints is Truth4::Both — at least one source asserts Is, at least one asserts Not. The K3 fail-closed projection at the query boundary rejects the disagreement. Switch to the default paraconsistent policy to receive the row tagged as Both, or reconcile the contributing standpoints’ axioms (§11.2).
OE1303ErrorLiveRuleNotRangeRestrictedA reasoner rule is not range-restricted (unsafe): a variable in the head, inside a negated (NAF) atom, or as a comparison/compute operand is never bound by a positive body atom. Such a rule degrades silently — an unbound head variable projects Null, an unbound negated/compared variable mis-evaluates — so it is refused at compile. Bind the variable with a positive body atom (standard Datalog range-restriction / safety). The named offenders are genuine VARIABLES: every multi-segment path in a value position is resolved (enum constant / axis value / type reference / declared individual) or refused (OE0227 / OE0620) at elaboration, so a qualified path like rigidity::anti_rigid can no longer reach this error — an offender containing :: indicates an artifact built by a pre-S0 toolchain; rebuild from source.
OE1304ErrorLiveNonComparisonOperatorA reasoner Comparison atom uses a non-comparison operator. Only == / != / < / <= / > / >= are meaningful as a rule-body filter; any other operator (e.g. +) makes the executor’s ordering test undefined and would silently drop every row, so it is refused at compile.
OE1305ErrorLiveTierNotYetImplementedRule classified at a tier the current runtime executor does not yet support.
OE1306ErrorLiveRuleExceedsExecutorTierRule’s classified tier exceeds the dispatched executor’s supported_tiers upper bound.
OE1307ErrorLiveComptimeNotStaticRule declared #[comptime] depends on runtime state (mutation, dynamic individual, or non-static relation).
OE1308ErrorLiveComptimeForbiddenOnMutate#[comptime] is not admissible on mutate declarations.
OE1309ErrorLiveStratificationNafCycleNAF dependency cycle prevents stratified evaluation; use SLG (expressive tier) or rewrite.
OE1310ErrorLiveSemiringMismatchProvenance witnesses combined under incompatible semirings.
OE1311ErrorLiveNestedAggregateNested aggregates (count { count { ... } > N }) require answer-subsumption (SLG-class) evaluation and are refused in v0.1. Flatten via an intermediate pub derive rule, or wait for the V1 SLG kernel.
OE1312ErrorLiveAggregateKindNotImplementedCollection/string aggregate kind not yet implemented. The folding kinds (count / count_distinct / sum / min / max / avg) evaluate at runtime today; collect / set_collect / string_join / percentile require the V1 SLG kernel (Expressive tier). The collection-kind subquery forms — collect { … } (List), set { … } (Set), one { … } (Option) — are refused under this code too: pre-refusal they silently lowered to count (a green-checked cardinality test instead of the documented collection semantics). Use count { … } / exists { … }, or an intermediate pub derive.
OE1313ErrorLiveNafAggregateForbiddenNegation-as-failure (not) cannot wrap an aggregate subquery (count { … }, exists { … }) in v0.1 — the result is unsound (the inner aggregate was silently dropped by lowering, pre-γ.7). Rewrite via an intermediate pub derive rule that exposes the aggregate result, then negate over it: pub derive any() :- exists { p(x) }; pub derive none() :- not any();. Lift planned alongside the V1 SLG kernel.
OE1314ErrorLiveEmptyAggregateBodyEmpty aggregate body (count { }, exists { }) is refused — the resulting cardinality is the trivially-vacuous count of the surrounding binding (always 1), which is almost certainly not what the modeler intended. Provide at least one atom in the body, or use a constant predicate.
OE1315ErrorLiveQuantifierNotYetA quantifier rule atom is refused because the executor can’t yet evaluate this shape as a true quantifier (emitting anyway would silently over- or under-derive). The supported universal forall v: T where Body, Head (≥2 where-atoms — the last is the consequent, the rest the domain) DOES evaluate: it lowers to the count-equality count { v: Body, Head } == count { v: Body }. OE1315 fires for the shapes that don’t yet: an exists-FOL binder (exists v: T where …), the paren restriction form (forall(path, T)), or a forall whose where clause has fewer than two atoms (ambiguous domain/consequent split). Rephrase via explicit aggregates or an intermediate pub derive; the count { … } / exists { … } subquery forms are unaffected.
OE1316ErrorLiveTemporalOpUnsupportedAn unsupported temporal operation reached the evaluator and is refused loudly rather than silently mis-evaluated: arithmetic outside date±duration / date−date / duration±duration (e.g. Date + Date, scaling a temporal value, or mixing a temporal value with a number), a chronological comparison across mismatched temporal types (Date vs Duration, or a temporal value vs a non-temporal one), a calendar-relative duration (P1M/P1Y) or sub-day component (PT…), or today()/now() inside a rule. Surfaced identically in the reasoner and the mutate body. Scalar day-granular date/duration arithmetic and chronological comparison are supported; interval and Allen-relation operations live in the std::time/std::allen library over this value layer.
OE1317ErrorLiveRecursionThroughAggregationA predicate’s derivation recurses through an aggregate over itself — an aggregate body (count { … }, exists { … }, or the forall count-equality encoding) references a predicate in the same recursive cycle, e.g. pub derive Fulfilled(c) :- …, forall x where x in c.parts, Fulfilled(x);. Stratified-aggregate semantics (Faber-Pfeifer-Leone 2010) require the aggregated predicate to live in a strictly-lower stratum, so recursion through aggregation has no well-defined fixpoint and is refused at ox check / ox build rather than crashing the runtime evaluator. If the aggregate is incidental to the cycle, break it with an intermediate pub derive that materializes the aggregated predicate in a lower stratum. If the aggregate is a universal over the predicate being defined (a forall / count-equality over child parts — recursion depth is data-dependent, so no intermediate derive can leave the cycle), rephrase it as negation-as-failure double negation: derive a counter-example helper with not P(child) (pub derive HasUnfulfilledChild(p) :- childOf(p, c), not Fulfilled(c);), then P(parent) :- …, not HasUnfulfilledChild(parent); — recursion through negation is evaluated under well-founded semantics.
OE1318ErrorLiveUnsupportedMutationFormA mutate body contains a statement form the runtime cannot yet execute (emit, …). The parser and elaborator admit the form but execution would abort at first invocation, so ox check / ox build refuse the artifact up front instead of shipping a mutation that dies at runtime. Rephrase the statement or wait for the executable form to land. match is executable in BOTH positions: value position (a let RHS, an update … set value, a return/tail value, a require guard, desugared to a Term::IfExpr chain) and statement position (arms running effects, desugared to an Operation::If chain).
OE1319ErrorLiveMatchPatternNotYetA match arm uses a pattern form that does not yet execute: a binding pattern (a bare identifier that does not resolve to a payloadless enum constant), a payload pattern (Some(x), Type { … }), a tuple pattern, an arm guard, a type-test arm, or an is-outcome arm. The executable subset is ordered first-match over CONSTANT patterns: payloadless enum constant paths (Status::Active), Int / String / Bool / Date literals, or-patterns of those (`A
OE1320ErrorLiveConditionalArmFieldNotTotalA rule-body conditional expression (a value if, or a match desugared to one) projects a field inside a conditional ARM that is not total (required) on its holder — the field is declared optional (T?), or no declaration of it is visible. The relational lowering hoists every arm’s projection into an unconditional $field::<f> join, and $field::<f> has no row when an individual lacks the field — so a row missing an optional field would be SILENTLY dropped even when the arm projecting it is never selected. Refused at ox check / ox build rather than mis-evaluated. Workarounds: split the conditional into one rule per arm (each joining only the fields that arm needs), or declare the field required. Projections of required fields inside arms, and projections in always-evaluated positions (the rule body proper, the outermost condition), are unaffected. Lazy presence-guarded branch joins are the tracked long-term fix.
OE1321ErrorLiveEffectInValuePositionA block in VALUE position (a let RHS block, a value-if branch, a value-match arm) contains an effectful mutate statement (update, delete, forget, require, for, emit). Value lowering reduces a block to its tail expression — the statements would not execute, so the effect would silently vanish. Refused at ox check / ox build instead. Use a statement-position if / match (whose branches DO run effects), or hoist the effect out of the value expression.
OE1322ErrorLiveStaticCheckInstanceVocabularyA #[static] check reads instance vocabulary. #[static] asserts compile-time discharge intent, and discharge is staged by what the body reads: a check is catalog-level — evaluated finally at ox check / ox build — iff every head parameter and body variable is catalog-sorted: a reflective sort (TypeRef, TraitRef, or Metatype; declaration structure read through specializes, implements, the type column of iof / meta), or an axis-value type (the element type of a pub metaxis Set/Typed domain, read through the catalog-closed $setAxis / $axis relations with n in meta(t).axis). This check binds at least one variable over individuals (a concept/relation predicate atom, a $field:: projection, or the entity column of iof / meta), so its vocabulary classifies it instance-level and it would silently reclassify to runtime discharge — exactly the drift #[static] exists to catch. Either rephrase the body over catalog-sorted variables only, or drop #[static] to accept instance-level (runtime + declared-EDB-at-build) discharge.
OE1323ErrorLiveMalformedCheckDiagnosticA check rule’s => Diagnostic { … } payload is missing or malformed. Diagnostic is check-surface syntax interpreted by the compiler (like the #[default] defeat-plane directive), not a user type — no import declares it, and its shape is fixed: exactly the fields severity: (the path Severity::Error / Severity::Warning / Severity::Info — nominal, closed set), code: (a string literal), and message: (a string literal, or format!("…{}…", args) with positional {} placeholders matching the argument count one-to-one). code: and message: are always required; severity: is required UNLESS the check is a trait-member impl whose trait pins the member’s severity (check Member(Self) => Severity::…;), in which case omitting severity: inherits the pinned one (a divergent restatement is OE0676); unknown or duplicate fields are refused; at: is reserved for span attribution (the LSP consumes it when it lands) and is refused until then. Named ({name}) or spec’d ({:?}) interpolations are refused — only the empty positional {} form evaluates; a brace placeholder in a plain (non-format!) message literal is also refused, since nothing would interpolate it. Literal braces are written {{ / }} — the escapes work in plain messages and format! templates alike. #[observe] is refused on a non-Error check — Warning / Info checks never guard, so there is nothing to opt out of.
OE1324ErrorLiveCheckCodeNamespaceA check’s code: string does not follow the user-code namespace discipline: the code must be ::-qualified (e.g. "Lease::E001" — a package/domain prefix, then the code), and the OE / OW prefixes are reserved for the compiler’s own catalog (this extends the compiler’s hygiene rule to user space — a user check masquerading as a compiler diagnostic would be indistinguishable in build output and tooling filters). Pick a namespace that names your package or standard ("OntoClean::C1", "HR::W014") and keep the compiler prefixes out of it.
OE1325ErrorLiveCheckMessageArgUnboundA format! argument in a check’s message: does not resolve against the check body’s bindings. Message arguments are evaluated per violation tuple, so every variable they mention (directly, or as the receiver of a field chain like c.cite) must be bound by the rule — a head parameter or a variable bound by a positive body atom — exactly the range-restriction discipline OE1303 enforces for rule heads. An unbound argument has no value at rendering time and would interpolate garbage (or drop the row) silently, so it is refused at ox check / ox build. Bind the variable with a positive body atom, or interpolate a bound one.
OE1326ErrorLiveTraitMemberNotYetA trait or impl body declares a form the compiler cannot elaborate. All five TRAIT member forms land end-to-end: rule-plane members (derive/check/query, slice 1) and invocation-plane members (fn/mutate, slice 3) elaborate, conformance-check, and execute. This gate remains for the genuinely unsupported shapes: trait-side DEFAULT member bodies (V1 bounded-generics territory — a default body cannot typecheck against Self’s fields without structural bounds; the OE0667 family), inherent (bare-impl) members (no trait contract, no dispatch story — a follow-on), and unrecognized member forms (associated const/type bodies, junk items). The member parses and is named in this diagnostic together with its declaring trait or impl; ox check / ox build refuse the program rather than shipping an artifact in which the member silently does not exist (v0.1 previously DISCARDED trait/impl body items without a diagnostic). Remove the member, move the default body into each impl, or declare inherent behavior through a trait impl.
OE1327ErrorLiveTraitMemberUncoveredA bare trait-member atom is called over an argument whose static type (the calling rule’s head-parameter annotation) is not FULLY covered by the trait’s impls. Coverage is a workspace-closed catalog scan: every instantiable declared S ⊑ T must satisfy S ⊑ target for some impl target — instantiable means NOT abstract (the type’s own modifier, or its introducing metatype’s, read from the wire — never a user axis name; the pre-S4 sortality token scrape is retired). The default is instantiable: an unmodified declaration obligates coverage, and the exemption is the explicit abstract opt-in. Under naive clause union an uncovered type would make the atom silently FALSE — the silently-vacuous shape this project refuses. Fixes: add the missing impl(s), declare the never-directly-instantiated supertype abstract, or make the partial dispatch explicit with the conformance guard implements(meta(p), Trait) as a body conjunct — the guard’s $implements join then excludes uncovered individuals visibly. A static type with NO covered instantiable subtype stays refused even with the guard written (the guard would be vacuous; the help says so).
OE1328ErrorLiveDuplicateCheckHeadTwo check declarations in the same module scope share a head name. derive rules union same-head clauses natively (the §7.3.1 disjunction idiom), but that idiom canNOT apply to checks: a check’s head carries payload identity — the => Diagnostic { severity, code, message } report, the guard classification, and the violation relation all belong to the head — so two checks sharing one head would cross-talk (one check’s violations rendered under the other’s severity, code, and message template, with garbage interpolation when the templates differ). Refused at ox check / ox build. Rename one check, or express the disjunction in a single check body (e.g. over a shared derive predicate whose same-head clauses union, then one check reading it). Trait check members are unaffected: each impl’s monomorphized member rule is qualified by its impl target (Trait::Member@Target) and keeps a distinct head.
OE1329ErrorLiveCheckHeadConsumedA rule-body predicate atom resolves to a check head. Check heads are observer-only (§7.1: check never populates the IDB) — a check’s violation set is a report with payload identity (severity / code / message), not a derived relation other rules may join. Consuming it would make derived facts depend on diagnostic machinery (and on whether a check happens to be discharged), the inverse of the architecture. Refused at ox check / ox build for every consuming rule mode (derive, check, query, bridge bodies). Derive from the underlying body predicates instead: factor the check’s violation pattern into a pub derive head, reference THAT from both the check and the consuming rule.
OE1330ErrorLiveTemporalQualifierOnWriteA write statement in a mutate body carries a valid-time qualifier (insert iof(p, T) at <expr>, during <expr>, since <expr>). The parser and elaborator build the qualifier faithfully, but the runtime write path never consumes it — every DML arm destructured it away, so the qualified write applied as if unqualified (the bitemporal extent stamped vt_start = vt_end = None), silently producing atemporal data for a user writing temporal assertions per the book. The storage substrate carries bitemporal extents and as-of reads are exact, but threading user-supplied valid-time through the write path (evaluating the qualifier Term, mapping at/during/since onto vt_start/vt_end, and extending the shared emit_* storage signatures across both backends) is work that is not yet wired. Refused at ox check / ox build rather than dropping the qualifier silently, the same fail-closed discipline as OE1318. Drop the qualifier to write at the current valid time, or wait for the bitemporal mutation forms to land.
OE1331ErrorLiveValueAggregateBraceFormA value aggregate (sum / min / max / avg) was written in brace form sum(expr) { atoms }. Only the cardinality aggregates count { … } / exists { … } take the brace form; a value aggregate uses the comprehension form sum(expr for x in Source, atom, …), whose comma-separated trailing atoms (relation joins, comparisons, type tests) refine the fold’s domain and whose grouping is the outer bound variables. Rewrite sum(e.amount) { posted(e, acct) } as sum(e.amount for e in Entry, posted(e, acct)). Refused at ox check / ox build rather than silently mis-folding — one spelling per aggregate role (the house single-spelling rule).
OE1332ErrorLiveAggregateOverUndefinedAn aggregate folds over a relation that carries well-founded-UNDEFINED atoms ($undefined::R is non-empty for an aggregated predicate). Aggregates evaluate over the definitely-true extent; folding when part of the input is neither true nor false would silently treat undefined as false (the undefined-as-false leak) — biasing sum / count low and min / max arbitrarily, with no diagnostic. Refused loudly at runtime instead, the same fail-closed discipline the WFS check boundary uses. The refusal is WHOLE-RELATION, not per-group: any non-empty $undefined::R companion trips it, even when the undefined tuples belong to a group key that the current binding would not fold — a conservative stopgap that never folds undefined-as-false. Three-valued aggregate intervals over the undefined set are the designed follow-up; for now, stratify the aggregated predicate so it has a definite extent (no recursion-through-negation feeding the fold), or aggregate over an intermediate pub derive that is itself definite.
OE1333ErrorLiveRoundingBuiltinArityA rounding builtin (round / round_half_even / trunc) was called with the wrong number of arguments. round(x) rounds to the nearest integer (ties away from zero) and round(x, n) to n decimal places; round_half_even(x, n) rounds to n places with ties to even (banker’s rounding — the money default); trunc(x, n) truncates toward zero at n places. All operate exactly over the numeric tower (Decimal stays Decimal, never via f64). Refused at compile rather than silently dropping the row.
OE1334ErrorLiveBindingLhsNotSimpleVarA body-level binding atom x = expr has a left-hand side that is not a fresh single-segment variable — a dotted projection (x.f = e) or a ::-qualified path (m::x = e). A binding introduces a NEW variable, so its left-hand side must be a bare identifier. = is the binding (assignment) operator in a rule body, distinct from the comparison ==; it is NOT a field-update operator (that is the mutate-body update … set { field = … } statement). Refused at ox check / ox build rather than falling through to a bare-path Boolean atom, which would silently drop the right-hand expression — the loud-or-working discipline (nothing silently dropped).
OE1335ErrorLiveBindingLhsAlreadyBoundA body-level binding atom x = expr names a left-hand side x that is ALREADY bound — by a prior positive predicate atom, a head parameter, a projection, an aggregate result, or an earlier binding. A binding introduces a FRESH variable; reusing a bound name was silently degrading into an equality FILTER (x joined against the computed value) rather than a binding, so two readings of the same = (bind vs. compare) collapsed with no diagnostic. Refused at ox check / ox build: use == to compare x against the expression, or pick a fresh name for the binding. (== filters over already-bound operands; = binds a new one.)
OE1336ErrorLiveBindingInComprehensionA binding atom x = expr (single =) appears as a trailing atom inside an aggregate comprehension (sum(… for v in S, …, x = expr)). Bindings are NOT a comprehension trailing-atom form: the comprehension body admits predicate joins, comparisons, type tests, and membership — filters that refine the fold’s domain — but a binding introduces a fresh variable whose safety the aggregate sub-scope does not check, so it is refused rather than admitted half-checked. Two rewrites cover every use: project the value directly into the fold (sum(u.v for u in T, rel(t, u)) instead of sum(w for u in T, rel(t, u), w = u.v)), or bind in the OUTER rule body and aggregate the bound variable. Refused at ox check / ox build with this directed hint rather than a generic parse error (== to compare is still accepted as a trailing filter).
OE1337ErrorLiveCalendarRelativeDurationA duration literal <int>.<unit> names a CALENDAR-RELATIVE unit (.months / .years) whose length in days depends on the anchor date — 1.months is 28–31 days, 1.years is 365 or 366 — so it has no fixed value in Argon’s day-granular Duration layer. The supported units are .days and .weeks (a fixed day count: <n>.daysn, <n>.weeks7n), which lower at rule-term resolution to a Duration literal that Date ± Duration arithmetic evaluates exactly. Admitting a calendar-relative unit would force a silent, anchor-dependent approximation — refused loudly instead. Use .days / .weeks, or compute the target date explicitly (e.g. an end-of-month date as data).
OE1338ErrorLiveDateIntrinsicArityA date intrinsic (today()) was called with arguments. The date intrinsics are NULLARY — today() reads the current valid-time of the evaluation (the reasoner’s evaluation clock, fixed for the whole fixpoint so a rule stays a pure function of its snapshot) and takes no parameters. A stray argument is refused at ox check / ox build rather than passed through as an un-evaluable application that would later surface as a generic term-shape failure. Write today().
OE1339ErrorLiveTemporalQualifierUnexecutableA mutate-body write’s valid-time qualifier could not be executed. Two cases: (1) during <window> — window-valued valid-time needs an interval value the surface does not yet carry, so it is deferred; use at <date> (valid-from a civil day), which IS executable. (2) the at <date> / since <date> expression did not evaluate to a Date — e.g. a bare arithmetic value where a #YYYY-MM-DD# literal was meant (the #date# silent-Int landmine: a bare 2024-01-01 is integer subtraction, not a date). The valid-time qualifier must evaluate to a Date (a #date# literal or a Date-typed value). Raised at runtime before any event is persisted, so the mutation commits nothing.
OE1340ErrorLiveBareDateArithmeticA bare YYYY-MM-DD in a rule body parses as INTEGER SUBTRACTION (2024-01-012024 - 1 - 1 = 2022), not a calendar date, and was silently accepted — even against a Date-typed position — modeling a date off by two millennia with no diagnostic (the #date# silent-Int landmine). Argon’s calendar-date literal is HASH-DELIMITED: write #YYYY-MM-DD#. The check fires only on the exact date shape — three zero-padded integer literals (4 / 2 / 2 digit widths) whose fields form a valid civil date (year 1000–9999, month 01–12, day 01–31) — so a genuine subtraction of differently-shaped operands is never flagged. Refused at ox check / ox build with a directed hint toward the real literal.
OE1341ErrorLiveRelationCardinalityExceededA mutate-body relation write (insert <rel>(…)) would exceed a relation endpoint’s declared finite max-cardinality (§5). The i-th bracket constrains how many DISTINCT values position i may take for a fixed combination of the OTHER positions — the standard UML association-end multiplicity. So in pub rel ParentOf(parent: Person, child: Person) [0..2] [*], the position-0 bracket [0..2] caps each fixed CHILD at two distinct parents; a third distinct parent for one child refuses atomically (the body commits nothing) under the closed-world default, counted over committed-plus-overlay tuples (read-your-writes). Before this gate the bracket parsed into a token-soup node no lowering read and the cap was silently ignored. Max-caps are the CWA-checkable half of a cardinality bracket; the min-card half is the deferred OW1342. Emitted by the runtime write path; an open upper bound ([lo..*] / [*]) imposes no cap.
OE1342ErrorLiveBodilessDeriveUnboundArgA bodiless pub derive P(...) — a derive head with no :- ... clause — is a GROUND FACT: it seeds P’s extent with the named tuple, and every head argument must therefore be a CONCRETE term (a declared individual in scope, an enum constant, an axis value, or a type reference). The named argument is none of these — it is a free variable, and a bodiless derive has no body to range-restrict it, so the tuple it would seed is undefined. (This is the bodiless-derive analogue of the range-restriction refusal OE1303 for rules WITH a body: there a head variable is bound by a positive body atom; here there is no body, so the argument must be a constant.) Declare the individual (pub fact T(name); classifies name into concept T), or add a :- ... body that binds the variable. To seed ground tuples on a derived predicate, this bodiless form over concrete arguments is the sanctioned idiom — it unions with P’s other derive clauses and rules over the same head; alongside it, declaring pub rel P(...) and asserting pub fact P(...) is equally valid.
OE1343ErrorLiveMalformedCardinalityA relation endpoint cardinality bracket is malformed (§5): the lower bound exceeds the upper ([3..1]), a bound is non-numeric, or the bracket contains junk tokens. Before this the bracket parsed into a token-soup node that no lowering read, so a malformed cardinality was silently dropped along with a well-formed one; now the bracket is interpreted into a structured cardinality and a malformed one is refused at ox check / ox build. Use [n] (exactly n), [lo..hi], [lo..*] (at least lo), or [*] (any).
OE1344ErrorLiveQueryCteNotYetImplementedA query select-body opens a with <name> = select …; common-table-expression (CTE) clause (§7.4) that does not yet execute. The CTE surface is documented but the binding is not wired into the query planner, so accepting one silently would drop the named sub-result and evaluate the outer select against nothing. Refused by name at parse — distinct from a generic typo — until the planner materializes CTE bindings. For now, inline the sub-query’s filter into the outer select … from … where …, or declare an intermediate pub derive and select over it.
OE1345ErrorLiveQueryGraphTraversalNotYetImplementedA query uses a graph-/path-traversal form (§7.4) that does not yet execute: a select shortest path … / select all_shortest path … projection, a select path <name> … path-binding projection, or a `… as mode walk
OE1346ErrorLiveQueryOptionalFromNotYetImplementedA query select-body uses an optional from … clause (§7.4) — the left-outer-join form that admits rows whose optional pattern has no match (binding its variables to null) — which does not yet execute. The clause is documented but the planner has no outer-join operator, so accepting one silently would drop exactly the rows it is meant to keep. Refused by name at parse until the outer-join lands. Split into two queries, or model the optional fact with an explicit Option-typed field, for now.
OE1347ErrorLiveQuerySetOpNotYetImplementedA query combines two select-bodies with a result-table set operator — union, union all, intersect, or except (§7.4) — that does not yet execute. The operators lex and the surface is documented, but the planner has no set-combination stage, so accepting one silently would return only the first select’s rows. Refused by name at parse rather than a generic token error. Combine the branches with multiple pub derive clauses sharing one head (union), or filter explicitly (intersect/except), for now.
OE1348ErrorLiveRuleRoleStepClosureNotYetImplementedA rule body uses a role-step transitive-closure navigation — x.Role+(y: T) (one-or-more steps) or x.Role*(y: T) (zero-or-more) (§7.3.1) — that does not yet execute. The closure surface is documented (the headline ontology path-traversal form) but the reasoner has no closure operator on a role step, so the +/* after a navigation parsed as stray arithmetic and died generic. Refused by name at parse until role-step closure lands. Write the closure as an explicit recursive pub derive reaches(x, y) :- x.Role(y); reaches(x, y) :- x.Role(z), reaches(z, y); for now.
OE1349ErrorLiveRuleOutcomeSuffixNotYetImplementedA rule-body predicate atom carries a reasoning-outcome suffix — is both(a, b), is ambiguous(a), or is timeout(a) (§7.3.1 / §14) — that does not yet execute. The is unknown outcome IS executable (it reads the well-founded undefined value); the multi-valued outcomes (both = paraconsistent over-determination, ambiguous/timeout = SLG resolution states) need the richer §14 reasoning-outcome surface. Before this, is ambiguous(a) / is timeout(a) parsed and were SILENTLY DISCARDED (lowered to the bare predicate, dropping the outcome) and is both(a, b) died on a generic parse error — both now refuse by name. Use is unknown for the WFS-undefined case for now.
OE1350ErrorLiveRuleTemporalAtomNotYetImplementedA rule body leads with a metric-temporal atom — ever, always, since, until, during, box_minus, diamond_minus, box_plus, diamond_plus (§7.3.2) — that does not yet execute. The DatalogMTL operator surface is documented and the Lean substrate models it, but the Rust reasoner has no temporal-fixpoint evaluator, so these keywords had no rule-atom production and fell through to a generic parse error. Refused by name at parse until the temporal reasoner lands. Model time explicitly with Date-typed fields and ordinary comparisons for now.
OE1351ErrorLiveUnsafeLogicBlockNotYetImplementedAn unsafe logic { … } block (§9.3) — the escape hatch that admits a full first-order-logic formula above the decidable tier ladder, opting out of the tier classifier’s termination guarantee — does not yet execute. The surface is documented for the fol tier but no FOL solver is wired in, so the block had no item production and died at module level with a generic parse error. Refused by name until the FOL escape hatch lands. Stay within the decidable tiers (structuralrecursive) for now.
OE1352ErrorLiveMutateUpsertNotYetImplementedA mutate body uses an upsert statement (§8) — insert-or-update keyed on identity, with optional on insert { … } on update { … } arms — that does not yet execute. The keyword is reserved and the surface is documented, but the write path has no upsert effect, so upsert had no statement production and fell through to a generic expression parse error. Refused by name at parse until upsert lands. Branch explicitly on existence with require + a conditional insert / update for now.
OE1353ErrorLiveMutateDetachDeleteNotYetImplementedA mutate body uses a detach delete <rel>(…) statement (§8) — delete a relation tuple and the individuals it solely connects — that does not yet execute. The detach keyword is reserved and the surface is documented, but the write path has no detaching-delete effect (only a plain delete tuple/iof), so detach had no statement production and died on a generic parse error. Refused by name at parse until detach-delete lands. Use a plain delete <rel>(…) and delete any orphaned individuals explicitly for now.
OE1354ErrorLiveAsyncFnNotYetImplementedA function is declared async (or uses .await) (Appendix B) — asynchronous evaluation — which does not yet execute. The async / await keywords are reserved against a future effect system but there is no async runtime, so async fn had no declaration production and fell through to a generic module-level parse error. Refused by name at parse until async lands. Declare a plain pub fn for now.
OE1355ErrorLiveConstDeclNotYetImplementedA top-level const <NAME>: <T> = <expr>; declaration (§19) does not yet execute. The form parsed but SILENTLY SWALLOWED its initializer — it emitted no event and bound no value, so a model could reference a constant that did not exist with no diagnostic (contradicting the no-hollow-features rule and STATUS’s every surface decl lowers to events). Refused by name at parse, rather than silently accepted, until const evaluation and the compile-time-constant plane land. Inline the literal at each use site, or model it as a field default, for now.
OE1356ErrorLiveSinkDeclNotYetImplementedA top-level pub sink <name> { … } declaration (§7.5) does not yet execute. The form parsed but SILENTLY SWALLOWED its brace body via balanced-token skipping — it emitted no event and validated nothing inside the braces, so arbitrary garbage between the braces was accepted with no diagnostic (contradicting the no-hollow-features rule). The companion emit statement is already refused loudly (OE1318); the sink DECLARATION now refuses by name too rather than swallowing, until sink publication has a runtime. A bare pub sink <name>: <Type>; declaration form (no body) is the documented typed-sink shape and is unaffected.
OE1357ErrorLiveRuleNegatedSomePayloadBindingUnsupportedA rule body negates an Option/T? payload binding — path is not Some(<ident>). The positive form is Some(a) binds a to the payload and the conjunction fails on None; under negation there is no payload to bind (the binder would range over nothing), so a bound is not Some(a) is incoherent. The intended meaning is the absence test, written path is None (true iff the field is absent) — refused by name rather than binding a meaningless variable. Use path is None for the negative test, or path is Some(a), not <p>(a) to negate a property of the payload.
OE1358ErrorLiveRuleOptionTestNotFieldProjectionAn Option/T? membership test is Some(a) / is None has a left side that is not a field projection. The test reads an OPTIONAL FIELD’s presence — a present field materializes one $field::<f>(holder, value) row, an absent one materializes none — so its left side must be a field access (p.age is Some(a)), not a bare variable or an expression with no relationalizable receiver. Refused by name rather than silently dropping the option test. Write <holder>.<field> is Some(a) / <holder>.<field> is None.
OE1359ErrorLiveRelationIrreflexivityViolatedA relation declared #[irreflexive] (a generic relation-algebra property — no element relates to itself, OWL IrreflexiveObjectProperty) has a self-loop R(x, x) in its extent. #[irreflexive] synthesizes a check rule over the declared relation’s own extent that fires on any tuple whose two positions are equal; this is that check firing. Either the offending self-pair must not be asserted, or the relation is not actually irreflexive and the directive should be removed. (The directive enforces the relation’s OWN extent — propagation to relations classified-by an irreflexive metarel is a recorded follow-up, not yet enforced.)
OE1360ErrorLiveRelationAsymmetryViolatedA relation declared #[asymmetric] (a generic relation-algebra property — R(x, y) forbids R(y, x), OWL AsymmetricObjectProperty) contains a mutual pair: both R(x, y) and R(y, x) are in its extent. #[asymmetric] synthesizes a check rule over the declared relation’s own extent that fires when a tuple and its converse both hold; this is that check firing. Either one direction of the mutual pair must not be asserted, or the relation is not actually asymmetric and the directive should be removed. Note asymmetry implies irreflexivity (a self-loop is its own converse), so #[asymmetric] alone already forbids R(x, x).
OE1361ErrorLiveRelationFunctionalityViolatedA relation declared #[functional] (a generic relation-algebra property — each source maps to at most one target, OWL FunctionalObjectProperty) has a source related to two distinct targets. #[functional] reuses the relation max-cardinality machinery: it synthesizes a [0..1] upper bound on the relation’s TARGET (last) position, which the write path enforces atomically — a second distinct target for an already-mapped source is refused before it commits (the same mechanism as OE1341). This code names the functional-property origin of that refusal so the modeler sees that a #[functional] directive, not a hand-written [0..1] bracket, is the constraint being enforced.
OE1362ErrorReservedRelationPropertyNotImportedRetired — no longer emitted. #[functional] re-homed from a #[builtin] stub to a genuine procedural macro in std::rel (it re-emits a rel with a [0..1] cardinality cap on the target endpoint via structural reflection, or pastes a guarding check on a metarel). It is no longer a registered directive, so an unimported #[functional] — like its siblings #[transitive]/#[irreflexive]/#[asymmetric] — is now refused as OE0705 (unknown attribute macro). This code is retained for historical numbering.
OE1363ErrorLiveMutationCallCycleThe mutation call graph contains a cycle — a mutate body invokes another mutation (directly, mutually, or itself) along a path that returns to its start (§7.5). A sub-mutation call is closed-nested: it runs the callee’s operations into the CALLER’s transactional buffer rather than evaluating to a fixpoint, so the whole transitive call tree is one atomic transaction that commits or aborts wholesale. A recursive cycle therefore has no terminating composed evaluation in v1 — it would unbound-recurse the runtime — so the call graph is required to be statically acyclic and the cycle is refused at ox check / ox build, naming the trail, rather than shipping a mutation that overflows the stack on first invocation (the same fail-closed discipline as OE1318). A trait-member callable edges to every impl body in its group (dispatch picks one at runtime, but any is statically reachable). Break the cycle; recursive mutation composition (fixpoint-to-quiescence) is a separately gated future feature.
OE1364ErrorLiveUnknownTermInBodyA derive / query / check / fn body contains an expression the elaborator could not lower — it degraded to the <unknown> lowering sentinel (Term::Var { name: "<unknown>" }), the fallback an un-lowerable expression form falls back to during expr/atom lowering. The sentinel resolves to no binding at runtime and surfaces as a generic “unbound variable” the first time the body is evaluated, so a body reaching a built artifact carrying one is a silent landmine (this is the same bug-class OE1318 closes for mutate bodies — the self-in-expression-position case — extended to every rule-plane and compute body). The sentinel is refused at ox check / ox build, naming the offending declaration, rather than shipping a rule/query/check/fn that dies generically on its first evaluation. Rephrase the offending expression into a supported form.
OE1365ErrorLiveNegatedWfsRelationA derive rule negates (not R(..)) a relation R that is evaluated under well-founded semantics in a DIFFERENT stratum — a relation whose extent can carry well-founded-UNDEFINED atoms because recursion-through-negation left part of it neither true nor false. The well-founded SCC materializes 2-valued at its boundary: only the definitely-true extent lands in R; the undefined tuples live in the $undefined::R companion relation. Ordinary derive-rule NAF reads only R, so a higher stratum’s not R(x) for a genuinely-UNDEFINED R(x) would read it as definitely-FALSE and over-assert the head — an unsound over-derivation with no diagnostic. Refused LOUDLY at ox check / ox build rather than silently evaluating undefined-as-false, the same fail-closed discipline OE1332 uses for aggregates over an undefined relation (the check boundary already excludes $undefined::R correctly via its K3 firing rule; derive heads do not yet). This refuses ONLY the genuinely-unsound case — a NAF edge whose target SCC is well-founded and is NOT the negating rule’s own SCC; ordinary stratified NAF over a fully 2-valued relation (no recursion-through-negation) is unaffected, and a same-SCC NAF is the recursion-through-negation the well-founded evaluator handles internally. Collapse the negation into the well-founded SCC: instead of splitting into a lower R stratum and a higher H :- .., not R(..) stratum, route H’s recursion through its OWN negation so {H, R} form a single NAF-cyclic SCC the engine evaluates by well-founded semantics directly (the documented win-move idiom in examples/robot_plan_execution/robot.ar ~115-140). Three-valued propagation of UNDEFINED into derive heads (the AFT pair-encoding) is tracked separately.
OE1366ErrorLiveCheckViolationA user-authored check rule fired at Severity::Error (static discharge). The check’s body matched over the package’s catalog / declared EDB, so the obligation it encodes is violated. This is the typed-channel carrier the language server uses to surface a fired check in-editor: the violation’s own namespaced code (e.g. Lease::E001) and its rendered message lead the diagnostic message, since a user check’s identity is the author’s ::-qualified string, not a compiler catalog code. ox check / ox build report the same violation through the user-diagnostic channel and fail the command (the loud-gate); #[observe] opts an Error check out of blocking, and Warning / Info checks render and pass — neither is carried through this code.
OE1367ErrorLiveNegatedOpenWorldDerivedA rule negates (not H(..)) a relation H whose extent can carry OPEN-WORLD-UNDEFINED atoms — H is (transitively) derived through a negation over an open-world (#[world(open)] / default_world = "open") relation, yet H itself is read closed-world. An open-world not C(x) over an absent C(x) is can (unknown), not a definite not, so H’s definitely-true extent omits those can rows; a 2-valued not H(x) then reads such a can row as definitely-FALSE and over-asserts the head — an unsound over-derivation with no diagnostic. Refused LOUDLY at ox check / ox build rather than silently evaluating open-world-undefined-as-false — the open-world analog of OE1365 (the well-founded case), the same fail-closed discipline. This refuses ONLY the genuinely-unsound case: a closed-world not H over a relation whose derivation depends on an open-world negation. To resolve: mark H’s concept #[world(open)] too (so not H reads open-world and tolerates the can), or restructure so the open-world negation does not flow into a closed-world-negated head. Full three-valued propagation of open-world-undefined into derive heads (the AFT pair-encoding) is tracked uniformly with the well-founded case.
OW1342WarningLiveRelationMinCardinalityDeferredA relation endpoint declares a non-zero MINIMUM cardinality (pub rel Married(a: Person, b: Person) [1..1] — every person must be married) that the closed-world write/check channel cannot soundly enforce in v0. Under CWA a build-time refusal would wrongly reject staged construction (relate the entity in a later mutation), and the field-access-time / evaluation-channel emitter that would actively check it is designed but not built in v0 (the same disposition as OE0207’s staged-construction note). The bracket is NOT silently accepted-as-enforced: it is parsed into a structured cardinality, PERSISTED on the wire (RelationDeclBody.cardinalities), the max-cap half IS enforced at the write path (OE1341), and this WARNING is emitted at ox check / ox build (by oxc-driver) naming the relation + position so the modeler knows the minimum is recorded-not-enforced. Full min-card-under-OWA enforcement is a recorded follow-on.

Cross-level instantiation bodies (19xx)

Field-coverage gates for cross-level instantiation bodies (§5.2). The MLT reasoning codes (categorization / partition / order / subordination / powertype) that once sat here are gone — MLT is an unprivileged package (packages/mlt), so those constraints are authored as the package’s own rules/checks over the neutral substrate, not as reserved compiler codes.

CodeSeverityStatusNameMeaning
OE1901ErrorReservedInstantiationFieldNotInTargetMLT cross-level body assigns = to a field absent from the target metatype (§5.2).
OE1902ErrorReservedInstantiationFieldShadowsMLT cross-level body declares a : field that shadows an inherited field (§5.2).
OE1908ErrorReservedIntrinsicPropertyMissingMLT body fails to bind a #[intrinsic] field required by the target metatype (§8).

Collection operators (24xx)

CodeSeverityStatusNameMeaning
OW2402WarningReservedRefineSingletonAsOptionA refinement [T; <=1] is more naturally expressed as T? (Option<T>) (§5.3).

Explanations

Codes with an extended explanation (also available offline via ox explain <CODE>):

OE0204 — UnknownField

Field access x.f where the receiver’s established type declares no field f (counting inherited fields and any : T narrowing in scope). In a rule body the error fires only on provable absence: an Argon individual can be classified under several concepts, and a field on any established concept is admitted, so f must be missing from every one of them. A receiver with no established concept (an unbound variable, or a path to a declared type/enum) is skipped.

Fix: declare the field on the concept, narrow the receiver to a type that has it, or correct the field name.

use std::core::{type, rel};

pub type Person { name: String, age: Nat }

pub derive adult(p) :- p: Person, p.age >= 18;   // ok: `age` is on Person
pub derive bad(p)   :- p: Person, p.income > 0;  // OE0204: no `income` on Person

OE0211 — IofInsertOnDefined

A concept defined with iff is defined, not asserted: its membership is derived from the refinement predicate, so you cannot insert iof into it — the substrate classifies individuals automatically whenever the predicate holds. (A primitive concept declared with where is the opposite: membership is asserted, and insert iof is exactly how you assert it.)

Fix — write the underlying state the definition reads, and let classification follow:

use std::core::{type, rel};

pub type Adult <: Person iff { self.age >= 18 };

pub mutate seed() {
    insert Person { name: "Mia", age: 19 };   // not `insert iof Adult`
    // Mia classifies as Adult automatically (age >= 18).
}

The same applies through <:-ancestors: if any defined ancestor derives the membership, the insert iof is refused.

OE0213 — IofInsertIntoBot

Bot () is the empty concept — the lattice bottom. By definition it has no instances: nothing is ever an instance of Bot. So insert iof(x, Bot) asserts a contradiction (x is a member of a category that, by definition, is empty) and is refused statically.

This is a sound, unconditional refusal — it follows from Bot’s definition alone, not from any two-concept disjointness analysis (that stays reserved). The dual, Top (), is the opposite: every individual is an instance of it, so a rule body Top(x) ranges over the whole domain.

If you meant to assert membership in a real concept, name that concept:

pub type Person;

pub mutate seed(p: Person) {
    insert iof(p, Person);   // not `insert iof(p, Bot)`
}

OE0605 — UnknownMetatype

Argon has no built-in ontology vocabulary. A declaration like pub kind Person reads kind as a classifier, and classifiers are not keywords — the leading introducer must resolve to a pub metatype that is in scope (§3.4). That is what keeps the language ontology-neutral: kind, class, rigid_sortal and friends ship in vocabulary packages (UFO, BFO, …), never in the compiler.

Even the no-commitment baseline type/rel are not ambient: they live in std::core and must be imported.

Fix — bring the baseline into scope:

use std::core::{type, rel};
pub type Person;            // ontology-uncommitted

or commit to a vocabulary you declare or import:

pub metatype kind = { };    // declares the `kind` classifier
pub kind Person;            // now legal

To make the baseline available across a whole package, set prelude = ["std::core::{type, rel}"] under [package] in ox.toml.

OE0668 — RefinementInvariantViolated

A primitive concept declared with where carries a necessary invariant: every member must satisfy it. This write would place an individual in the concept while the predicate evaluates to a definite false, so it is refused.

Three-valued by design: only a definite false blocks the write. If the predicate is unknown (a field the data has not supplied yet), the write is allowed — absence of information is not a violation.

use std::core::{type, rel};

pub type Adult <: Person where { self.age >= 18 };

pub mutate admit() {
    insert Adult { name: "Lee", age: 15 };   // OE0668: 15 >= 18 is definitely false
    insert Adult { name: "Ada", age: 21 };   // ok
    // age unknown -> allowed (unknown, not false)
}

Fix: write a value that satisfies the invariant, model the looser set with a weaker where, or — if membership should be derived rather than asserted — use an iff definition instead.

OE0239 — FactReferencesDerivedPredicate

A predicate in Argon has a single origin: its extent is either EXTENSIONAL (asserted as ground facts) or INTENSIONAL (computed by derive/query rules) — never both. pub fact P(...) asserts into an extensional relation, but here P is a rule head, so the seed fact would key a different relation node than the rule reads and silently drop out of the fixpoint: no error, wrong answer. Argon refuses at ox check / ox build rather than emit an artifact that mis-derives.

To give a derived predicate ground tuples, keep it single-origin: seed the head with a bodiless derive clause, or read a base relation. Note that rule bodies must be range-restricted — bind each head variable with a positive atom, not a bare comparison (p.income > 0 alone leaves p unbound):

use std::core::{type, rel};

// a base relation the rule reads (seed it with `pub fact HighEarner(...)`),
// unioned with the rule clauses over the same head:
pub rel HighEarner(Person);
pub derive owes_tax(p) :- HighEarner(p);
pub derive owes_tax(p) :- p: Person, p.income > 0;