Diagnostic Reference
Every error, warning, and lint the Zolo toolchain emits. Click a code to see the full explanation, the typical cause, and the recommended fix.
Lint
24float-equalityFloating-point equality is imprecise. Use `~=` (adaptive tolerance), `!~=`, or `math.approx_eq_abs/_rel(...)`. For exact comparisons use the `decimal` type.
unused-variableA `let`-bound variable or parameter is never read. Prefix the name with `_` to silence the lint intentionally.
unused-functionA top-level function is never called and is not marked `pub`, `@test`, `@bench`, `@export`, an HTTP route, or `main`.
unused-importAn imported name is never referenced in the file.
shadowed-variableA `let` re-binds a name from an outer scope. Shadowing is sometimes intentional; rename one binding to silence the warning.
dead-codeCode after `return`, `break`, or `continue` is unreachable.
naming-conventionFunctions/variables use `snake_case`; structs/enums/traits/effects use `PascalCase`.
non-exhaustive-matchLegacy alias: closed matches are now checked once by the type checker as `TE829`. Kept so older links keep a migration target.
must-useA function or type annotated `@must_use` returned a value that the caller discarded. Bind it (`let _ = ...`) or consume it.
deprecatedA function annotated `@deprecated` was called. The annotation's message explains the replacement.
infinite-loopA `loop`/`while true` block has no reachable `break`/`return`.
optional-typoA `Some(...)` / `None` / `?.` / `??` use that looks like a typo or misuse of the optional API.
unreachable-patternA pattern can never match because an earlier arm already covers it.
max-line-lengthConfigured via the project's lint config. Default is permissive; tighten in CI if you want hard limits.
max-nesting-depthDeep nesting hurts readability. Extract helpers or use early-return guard clauses.
max-parametersLong parameter lists are a code-smell. Consider grouping related parameters into a struct.
max-function-lengthBreak the function into smaller helpers.
unknown-reprOnly `@repr(C)`, `@repr(packed)`, `@repr(transparent)`, and `@repr(zolo)` are recognized.
transparent-multi-field`transparent` only applies to single-field newtype-style structs.
layout-in-default-repr`@layout` only takes effect alongside an explicit `@repr`.
align-not-positiveAlignment must be a positive power of two.
align-not-power-of-twoHardware alignment rules require power-of-two values (1, 2, 4, 8, ...).
align-too-largeThe requested alignment exceeds the maximum the target platform supports.
size-not-positiveSize cannot be zero or negative.
Parse
05P0001The lexer reached end-of-file (or end-of-line in some contexts) before finding the closing quote of a string literal.
P0002The parser expected a specific token (e.g. `}`, `)`, identifier, type) but found something else. Usually a missing brace, paren, or punctuation.
P0003A token appeared where the grammar does not allow it — typically a stray symbol, a misspelled keyword, or a missing separator on the previous line.
P0004A parse-level error that did not match a more specific classifier. Read the diagnostic message for the precise cause.
P0005A `<!-- -->` comment was written between `<` and `>`, where HTML itself does not allow one either. Inside a tag, use Zolo comments: `//` or `/* */`. In the children of an element `<!-- -->` is fine.
Type
168E0001Equivalent to `TE001`. Emitted by the legacy message-pattern classifier when the new typeck did not attach a code.
E0002Legacy alias for `TE100`.
E0003Legacy alias for `TE101`.
E0004Legacy alias for `TE004`. The variable was declared with `let`; use `let mut` to allow reassignment.
E0005Legacy alias for `TE102`.
E0006A struct literal omits one or more required fields.
E0007Legacy alias for `TE110`.
E0008The value being returned does not match the function's declared return type.
E0009A name (function, variable, field, variant) was declared twice in the same scope.
E0010A type annotation refers to a type that the compiler cannot find.
TE001The value assigned to a `let` binding does not satisfy the declared type annotation.
TE002The value assigned to a `const` binding does not satisfy the declared type annotation.
TE003`const` requires a constant-foldable expression. Use `let` for runtime values.
TE004`let` bindings are immutable by default. Use `let mut x = ...` to allow reassignment, or use a fresh `let` shadow.
TE005Operators like `+=`, `-=`, `*=` require both sides to be numeric (or strings for `+=`).
TE006The function declared a tuple return but the actual `return` statement provides fewer values.
TE007The function returns more values than its declared single-value return type can hold.
TE008An array literal mixes incompatible element types; arrays are homogeneous.
TE009Binary arithmetic requires both operands to be numeric and (in strict mode) the same numeric type.
TE100The name is not declared in any enclosing scope. The compiler attaches a "did you mean?" suggestion when a similar name exists.
TE101The callee in a function-call expression is not a callable type.
TE102The struct does not declare this field. "Did you mean?" suggestions are attached for near-matches.
TE103A type annotation or enum-variant field references a type the compiler cannot resolve.
TE104The receiver type does not have a method with this name. Check spelling, imports, and trait visibility.
TE105A bare name matches a known standard-library module (`math`, `json`, `http`, `os`, …) that was never brought into scope. Unlike TE100, the compiler recognises the name and tells you exactly which `use` line is missing.
TE107A struct literal omits a field that has no default value and no zero-value fallback. Every non-defaultable field must be provided explicitly at construction time.
TE108A struct decorated with `@derive(Default)` has a field whose type has no zero value and no explicit default, so no `Default` impl can be synthesised for it.
TE109A struct field is written without a type annotation, relying on its default to infer the type (`name = value`) — but the default's type is ambiguous (e.g. `nil`, or an expression that resolves to `any`).
TE110The number of arguments passed does not match the function's parameter count.
TE111An argument's type does not match the corresponding parameter's declared type.
TE112Two or more `using`-embedded fields declare a field with the same name, so a `.field` access on the outer struct can't tell which embed to promote it from.
TE113A field marked `using` must embed another struct — its fields are what get promoted. A scalar, or any type that isn't a known struct declaration, has no fields to promote.
TE114An enum opted into numeric discriminants (a backing type, or an explicit `= n`) but is generic or has a payload-carrying variant. Discriminants only make sense for a flat, all-unit-variant enum.
TE115A variant's discriminant is outside the declared backing type's range (`enum E: u8` limits it to `0..=255`), so it could not round-trip through `to_int()`/`from_int()`.
TE116Two variants of the same enum resolved to the same integer — either two explicit `= n` values collide, or an auto-incremented value landed on one already taken.
TE117Under `@stable` auto-increment is disallowed: inserting a new variant in the middle would silently renumber every variant after it, breaking the encoding the annotation promises to keep.
TE118A variant's `= expr` discriminant either didn't evaluate to an integer at compile time, or couldn't be evaluated as a compile-time constant at all.
TE119An `@flags` enum is generic or has a payload-carrying variant. `@flags` models a bitmask over a fixed, flat set of unit variants — there's no room for type parameters or payloads.
TE120Each `@flags` variant must be either a fresh single bit (auto-incremented or an explicit power of two) or a named composite built only from bits declared above it.
TE121A flag's value is out of range for the enum's backing type — `enum: u8` bit-flags top out at `255` (bit 7).
TE122Two single-bit flags in the same `@flags` enum resolved to the same bit, usually because both were given the same explicit value.
TE123A destructuring pattern — `let Struct { … } = expr`, an anonymous `let { … }`, a parameter pattern, or a struct-destructuring assignment — names a field the struct doesn't have.
TE124The `else` block can fall through. If it did, execution would continue into the pattern bindings using a value that did NOT match, so every path through `else` must return, panic, break or continue.
TE125The pattern might not match (an enum-variant pattern, an array-length pattern, …) and has no `else` clause. Without one, a non-matching value would silently bind nonsense.
TE126An anonymous struct pattern needs to know which struct it destructures, but the value's type doesn't resolve to a concrete struct — usually because it has no type annotation.
TE127A named struct pattern in parameter position (`fn f(StructName { … }: T)`) names a different struct than the parameter's own type annotation.
TE128A struct literal's trailing spread (`Struct { ..source }`) has a `source` that isn't a struct or record, so there are no fields to spread in.
TE129A tuple-destructuring assignment (`(a, b, c) = expr`) has a different number of targets than `expr` has values.
TE130Compound operators (`+=`, `-=`, …) have no per-element meaning when the left-hand side is a whole pattern, and `..` spread makes no sense as an assignment target.
TE131A named argument (`f(name: value)`) does not match the callee's declared parameters — an unknown or duplicate name, a positional argument after a named one, a skipped middle parameter, or a callee with no locally-known signature.
TE132The `_` placeholder is only valid as a direct argument in the RHS call of a `|>`/`?>` pipe stage (at most one per stage), or as the head of a field/method/index chain used as a call argument (`_.field`). A stray `_`, a second `_` in the same pipe stage, or `_` as a pipe's left-hand side are all rejected.
TE133A real, declared enum was identified for this site — as the base of `EnumName::variant`, or as the type of a scrutinee matched against a `.variant` shorthand pattern — but the variant name doesn't match any of its declared variants. A "did you mean?" suggestion is included in the message when a close match exists.
TE134The name is part of the VM's always-in-scope prelude but the native/LLVM backend has no implementation for it. Building anyway would silently evaluate it to `nil` and exit 0, so the build fails instead.
TE135A native/LLVM-only check: a bare identifier resolved to nothing at all. Without a Lua prelude to fall back on, it would silently lower to `nil` at runtime — the "typo turns into a quiet no-op" class this catches at build time.
TE136The `.Variant` shorthand recovers its enum from the type the surrounding position expects, and this position supplies nothing usable — no expected type at all (an un-annotated `let`, an argument to a callee with no known signature), an un-pinned generic type parameter, or a type that is not an enum. Annotate the binding or write the qualified `Enum::Variant` form.
TE137The `.Variant` shorthand resolved its enum from the position's expected type, but that enum has no variant by that name. A "did you mean?" suggestion is included when a close match exists. The pattern form of the same mistake reports `TE133` instead.
TE138A native/LLVM build could not splice a declaration module: either a user declaration starts with the compiler-reserved `__zolo_std_` prefix, or a reachable declaration-module function references a sibling item the linker cannot carry into the final program. Either case would let the AOT build silently diverge from the VM.
TE139`<style>` and `<script>` are raw text elements: their content runs verbatim until the matching `</style>`/`</script>`, with no nested markup and no `{expr}` interpolation. Reaching the end of the file before that closing tag reports TE139 instead of the generic "unclosed element" message — usually a forgotten closing tag, or a `</tag`-shaped string inside the content (e.g. a JS string literal) that closed the block early.
TE140A build-time Resource Graph recipe (`Resource.dir(...).seal()`) could not be sealed into its immutable Resource Image — a missing or non-directory path, an `include` pattern that matched nothing, a path escaping the resource root, a logical-path collision, or a file that could not be read while the snapshot was being sealed. There is no runtime fallback to the working directory: the build fails instead.
TE141The compiler received a malformed internal Resource Graph value, or a sealed Resource Image failed its integrity checks — an invalid recipe field (`root`, `includes`, `excludes`) or corrupted build state, distinct from `TE140`'s actionable input/sealing failures.
TE142A `;` placed after a block's final expression suppresses its value, so the block concludes `void` instead of yielding a result. `TE142` fires when that terminator-caused void is used where a value is required — bound to a `let`, passed as an argument, and so on.
TE143A function declares `-> T`, but a `;` after its final expression suppresses that value, so the body concludes `void` instead of a `T`. Unless another `return expr` supplies the value, the function can never satisfy its own signature.
TE144The field declares `get` but no `set`, so assignments after construction are not allowed.
TE145Accessing `self.<same-field>` inside its accessor would recurse; use the contextual backing name `field`.
TE146An accessor may inherit or narrow its field visibility, but it cannot expose a private stored field publicly.
TE147`?` propagates failure but unwraps success. A function returning `Result` or `Option` must wrap that success explicitly with `.Ok(...)` or `.Some(...)`.
TE148A `tw"..."` literal must be a static list of Tailwind class names. Interpolating a value into it (`tw"bg-{color}-600"`) would hide part of the class name from the Tailwind build-time scanner, so Zolo rejects it — pick between complete literals using ordinary control flow instead.
TE150Inline expansion requires a real Zolo body; native and plugin declarations must use a Zolo wrapper.
TE151Use exactly one of `@inline`, `@inline(always)`, or `@inline(never)`.
TE152An always-inline body cannot recursively expand itself; use a hint or split the recursive core.
TE153The always-inline contract needs a supported hygienic body; simplify it or downgrade to bare `@inline`.
TE201Strict typing requires every `let`/`const` to have an explicit type annotation.
TE202Strict typing requires every function parameter to have an explicit type.
TE210A structured derive returned syntax that cannot be inserted at its destination; derive results must currently be `Syntax<.Items>` or `Syntax<.Item>`.
TE211A `${value}` hole received a value with no safe source representation; insert a primitive or `Syntax<K>` node instead.
TE212`syntax.ident(text)` received text that is not one valid, non-keyword Zolo identifier.
TE213A `${..values}` spread received something other than a list or tuple of syntax nodes from one compatible category.
TE214The generated items escape the expansion scope declared by `@derive_for`, such as an unrelated free function from an impl-scoped derive.
TE216A `@derive_for` function returned a value other than the supported `str`, `Syntax<.Items>`, or `Syntax<.Item>` results.
TE217A namespaced derive attribute contains an unknown, duplicate, missing, non-literal, or incorrectly typed option.
TE218A type uses `@derive(T)`, but no deriver for `T` is available in scope. Zolo never skips this silently — a misspelled name must not produce a partially generated program that only fails at runtime. Import or declare the public function that exposes the deriver, conventionally exported under the same name as the capability.
TE220`await` received a value whose known type is neither `Future<T>` nor `Task<T>`. Only those two wrappers can be suspended on; an ordinary value is already available and has nothing to await.
TE221`yield` is only valid inside a generator declared with `fn*`. An ordinary or `async fn` produces a single result and exposes no pull iterator to yield into.
TE222A generator (`fn*`) used `return value`. Termination and yielded items are separate concerns in a generator: `return` may stop it early, but its value is never produced as an iterator item — use `yield` for that.
TE223A `yield`ed value does not satisfy the generator's declared element type. Every `yield` inside `fn* ... -> T` must produce a value assignable to `T`.
TE224`await` appeared inside a `fn*` generator. Async generators have no scheduler contract shared by every backend yet, so Zolo rejects the combination instead of letting one backend resume it with different semantics than another.
TE225`break :label` or `continue :label` names no lexically active loop. Labels never cross a function/lambda boundary, and a `spawn`ed task or a callback scheduled with `every`, `after`, or `timeout` starts its own control-flow region, so it cannot jump to a loop in the caller.
TE226Two nested, simultaneously active loops declare the same label. A labelled exit would be ambiguous to a reader, even though the innermost declaration could be resolved mechanically.
TE227An unlabelled `break` or `continue` appears outside a loop. These statements can only transfer control within an enclosing `loop`, `while`, or `for`.
TE228A `break` carrying a value targets `while` or `for`. Only the unconditional `loop` form is a value-producing expression, so a value-carrying `break` is only valid there.
TE229The values carried by reachable `break`s disagree with the result type of a `loop` expression. A bare `break` contributes `void`, so it cannot exit a loop expected to produce a non-void value.
TE233`timeout duration { ... }` returns `Result<Any, TimeoutError>`. The timeout failure is ordinary typed control flow — it is not an untyped record, and it is never silently converted to the successful value.
TE301The number of type arguments supplied does not match the generic's declared parameter count.
TE302A trait bound, `impl` block, or `where` clause references a trait the compiler cannot find.
TE303An `impl Trait for Type` is not coherent with its trait declaration — either it adds a method the trait does not declare, or another implementation already satisfies the same parameterized target and trait instance.
TE304A method in `impl Trait for Type` does not match the trait after substituting `Self`, trait arguments, associated types, and method-generic parameters — parameter types/qualifiers, return type, generic bounds, and effect rows are all part of the contract.
TE305An implementation omits a required associated type, defines it more than once, names an associated type the trait does not declare, or supplies a type that fails the associated type's bounds.
TE480An implementation selected a concrete associated type that does not satisfy a bound the trait declared for it. The diagnostic names the implementation, the projected associated type, and the failed requirement — the original type is preserved, never silently widened to `Any`.
TE481A trait declares an associated type with no default, but an implementation does not define it, so the compiler cannot project `Self::Item` (or another associated name) from that implementation.
TE482The concrete type implements the requested trait name, but with different type arguments. Trait witnesses are exact — implementing `Sink<str>` does not prove `Sink<int>`.
TE486A value typed as a union can be used without narrowing only through members shared by every alternative. Reading a field or calling a method that some alternatives lack would be valid for one runtime value and invalid for another.
TE708A warning, not a build failure. A `for` loop produces a list of rows and the row carrying an `@island` component has no `key` — the client-side morph then rewrites the row node-by-node on reorder instead of patching it in place, and the island loses its hydrated DOM state (signals reset, focus and scroll are lost).
TE719An event handler inside an `@island` contains an expression the Verniz client lowering cannot represent as JavaScript. Server rendering could still produce the control, but publishing it without its handler would create an interactive-looking element that does nothing, so the build fails instead.
TE720An assignment targets a derived signal declared with `let<signal>`. A derived cell is defined by its initializer and recomputed from the source cells it reads — it is not writable state, so assigning to it would make it disagree with its own dependency graph.
TE721An `effect` inside an `@island` contains behavior the Verniz client lowering cannot compile to JavaScript. Unlike server rendering, an island effect has no server-side half that can preserve the behavior — if it is not emitted to the client it never runs, so the build is rejected instead of silently dropping it.
TE727A warning, not a build failure. A function declares its own `key` parameter, but `key` is a reserved markup attribute (spec V24) that is always routed through the extras map — it never reaches the function's own `key` parameter, which silently falls back to its default. The build succeeds and nothing else looks wrong.
TE730`@(expr)` compiles to a CSS custom-property bridge (`var(--…)`), which only exists in declaration values — after the `:`, before the `;`. In a selector, a property name, or an at-rule prelude there is no `var()` to bridge to, and splicing user text there is a deliberate anti-feature. Move the dynamic part into a value, or toggle static classes in the markup.
TE731A `<style children={expr}>` carries runtime content the compiler cannot see, so it can neither hoist nor scope it — scoping unknown text would be a lie. Spec §6.1: dynamic content must opt into `global` explicitly (`<style global children={…}>`), the one style form that stays a render node.
TE732A `@()` value travels as a CSS custom property, and only `str`, `int`, and `float` serialize into one. A value typed `bool`, `View`, map, struct, or function is rejected at compile time — at render it would stringify into garbage or vanish. Untyped (`Any`) values stay silent: this error never guesses.
TE733`@()` compiles to `var(--…)`, and CSS has no string concatenation in plain values — `var(--w)px` is a browser-dropped syntax error, not "number plus unit". Write `calc(@(x) * 1px)` or interpolate the full string (`@(f"{x}px")` — inside `@()` you are back in Zolo). `!important`, `/` and `*` in `calc()` are legal no-space neighbors.
TE734`:global(…)` exempts one compound from the hermetic scope stamp. An empty wrapper (`:global()`) exempts nothing, and a nested one (`:global(:global(a))`) escapes an escape — both can only be mistakes. In a `<style global>` body `:global()` is not Zolo syntax at all and passes through untouched.
TE735A warning, never a build failure. Hermetic scoping stamps every compound with the component class, so a selector naming a class/id/tag the component's own markup never produces is a dead rule — and `:root` under scope is structurally dead. Comes with a did-you-mean (edit distance ≤ 2) and the component's rendered set. Dynamic class/id values or `el`/`raw` calls open the set and suppress the warning — it never guesses.
TE736A scoped `<style>` belongs to its surrounding component fn — the fn's class stamp is what the selectors scope to. In a top-level statement or an `impl`/`trait` method there is no component, so there is no scope. Add `global` (a static `<style global>` outside a component renders in place) or move it into a component fn. A body with `@()` reports this even under `global`: its values need a component root element.
TE737Every `@()` value travels as a CSS custom property on the component's root element (the element literal in tail position), inheriting down the DOM. A component that delegates its whole view — no element root of its own — gives the values nowhere to ride. Make the tail an element literal (a wrapper `<div>` works) or drop the interpolation.
TE738A warning, never a build failure. Property names are checked against a curated table shipped with the toolchain (static data, no registry download); a near miss comes back with a did-you-mean (edit distance ≤ 2). Names starting with `-` — vendor prefixes and `--custom` properties — are never checked, and neither are at-rule descriptors (`@font-face`'s `src`, …). A property newer than the table costs a squiggle, never a release.
TE740A known HTML attribute is not valid for the authored element. Verniz validates native tags against its versioned DOM table; component props still go through the ordinary named-argument diagnostics.
TE741A two-way `bind:` binding is unsupported on the element, or its known source type is incompatible with the target DOM property — for example binding a `str` cell to `bind:checked`, which expects `bool`.
TE742An event handler attribute names an event Verniz does not recognize on that element. Event names use their DOM attribute spelling, such as `onclick`, `oninput`, and `onchange`.
TE743A void HTML element such as `input`, `img`, or `br` was written with children or an explicit closing tag. Void elements can never have content, so use the self-closing form instead.
TE744A high-confidence accessibility check: an `<img>` has no alternative text, or an interactive control has no name a screen reader can announce. It only fires when the missing name is certain — dynamic content, `children`, or an `HtmlAttrs` spread may still supply it at runtime.
TE745A known ARIA attribute or role is used with an invalid spelling or value, or a label targets an element id that does not exist in the authored markup.
TE746A `ref` target cannot receive a browser element. A `ref` must be an optional `DomRef` source cell (`var<signal> name: DomRef = nil`) declared inside the owning `@island`.
TE747A `{...spread}` is incompatible with its target. Dynamic forwarding onto a native element must be typed `HtmlAttrs`; a component spread must expose statically known record fields so ordinary prop checking stays active.
TE748An event modifier (`prevent`, `stop`, `once`, `capture`, `passive`, `self`) is unknown, duplicated, or combined incompatibly — `passive` cannot be combined with `prevent`.
TE749An attach contract cannot be fulfilled — the compiler catches statically empty portal targets, and the development attach verifier also reports missing portal targets, stale island markers, invalid binding properties, and refs that do not belong to the island.
TE750A lifecycle member such as `pending`, `error`, or `state` was read from an ordinary function reference. Only a reference to a function declared `@action` has the nominal `ActionFn<...>` type and a client-side lane.
TE751Code outside any `@island` tries to observe an `ActionFn`'s lifecycle. An action reference stays callable on the server, but `pending`, `state`, `retry`, and the rest of its observable lifecycle are browser-owned capabilities that cannot cross an island or wire boundary.
TE752A mutation action requested an unknown policy, or a superseding/cancellation policy such as `.Latest`. A mutation already accepted by the server may still commit even after the client stops caring about its response, so cancelling only the client continuation would make the UI lie about the effect.
TE753An `ActionFn` returning `Result<_, E>` is called by an island that never observes the lane's failure state — reading `.error`/`.state`, or calling `.try_run(...)`. Without an explicit observer, a validation or transport failure is easy to miss.
TE754A `.lane()` was created directly inside a rendered `for`. An explicit lane owns mutable client lifecycle state, but a list iteration has no stable lexical identity once rows are inserted, removed, or reordered.
TE763A value crossing between Zolo and browser TypeScript has no deterministic JSON representation the Wire bridge accepts — the bridge never falls back to `any`. Functions, closures, handles, `ResourceFs`, non-string map keys, and unmarked user types stay on their origin side; structs/enums need `@wire`.
TE764A declaration marked `@secret` is reachable from a `@wire` type or an `@action` browser contract. Shipping it would place a private value in a generated declaration, codec, request, response, or browser bundle — removing `@secret` only to silence the diagnostic is unsafe.
TE775Verniz could not turn an authored Markdown/JSON/TOML/YAML file into the metadata struct declared by `content.collection` — a missing or mistyped frontmatter field, an unparseable date, a non-portable path, or (for `ContentTransform`) a route callback/alias/fallback problem.
TE820A generic function is called with a type argument that doesn't implement a trait required by one of its bounds.
TE821An operator is used on a generic type parameter that carries no matching trait bound. Without it the compiler can't guarantee the operation is valid for every possible type argument.
TE822A bound in a function signature names a trait the compiler doesn't recognise.
TE823An operator is used on a concrete struct/enum value whose type doesn't implement the required trait. Without it there's no method to drive the operator, so it would crash at runtime.
TE824Qualified trait paths must be `core::<module>::<Trait>` or `std::<module>::<Trait>`, naming a `pub trait` actually declared there — in a generic bound and in an `impl` header alike.
TE825An `impl Trait for Type` is missing one or more required methods (those without a default body). Method and operator dispatch would otherwise fail at runtime.
TE826A collection method (`each`, `filter`, `len`, …) was called on a `Result` or `Option` wrapper directly. Unwrap it first with `?>`, `?`, or `.unwrap()`.
TE827`?.` is null-safe chaining, not fallible unwrapping. A `Result` or `Option` is never `nil`, so the chain runs over the wrapper itself. Use `expr ?> .m(...)`, `let v = expr?`, or `expr!.m(...)` instead.
TE828`for x in expr` needs `expr` to produce a sequence. Zolo iterates built-in collections and any type implementing `Iterator`/`IntoIterator`; a struct or enum implementing neither gives the loop nothing to produce.
TE829`match` on a closed type — `bool`, an enum (including payloads), a closed-payload optional, a closed union, or tuples/records of closed fields — has unguarded arms that do not cover every possible value. A guarded arm never proves coverage, because its guard can evaluate to `false`.
TE830An enum pattern names a real variant but destructures it with the wrong payload shape — unit, tuple, and struct variants each require their own pattern form, and tuple arity or struct fields must agree with the declaration.
TE831Every alternative of an or-pattern (`A(x) | B(x)`) must introduce the same names with compatible types, since the match body runs after any alternative succeeds and can read whichever name it bound.
TE832Postfix `?` and the fallible pipe `?>` require a value that can fail — `T?`, `Option<T>`, or `Result<T, E>`. Applying either to a statically plain value has no failure path to propagate.
TE833Postfix `?`/`?>` returns the matching `nil`, `Option.None`, or `Result.Err` from the enclosing function, and that failure must be compatible with its declared return type. `Option.None` is not interchangeable with `Result.Err`, and a nilable failure is never silently boxed into either enum.
TE834`?.` and `??` are nil-only operators, but `Option<T>` and `Result<T, E>` are boxed enum values — neither wrapper is itself `nil`, so `??` cannot unwrap it. Use postfix `?`, pattern matching, or an explicit wrapper method such as `unwrap_or` instead.
TE835`as` performs only compiler-known casts — it does not parse text, compute truthiness, serialize data, or run a conversion implemented by a user type. Use `parse::<T>()`, `to_string()`, `try_into::<T>()`, or an explicit comparison instead.
TE836`value as? T` promises an exact, runtime-checked conversion, but the source and destination types have no value-preserving checked path — for example parsing text is not casting. Use `parse`, `try_into`, or a numeric cast policy instead.
TE837A numeric `as` may narrow a range, change signedness, discard a fractional part, or round an integer too large for the destination float. Use `as?` when only an exact value is acceptable, or `cast` with a named rounding/overflow policy when loss is intentional.
TE838A bare `as` cast from `Any` cannot prove the runtime value actually has the requested type, so Zolo rejects it. Use a checked cast (`as?`) or flow narrowing (`is`) instead.
TE839`value as str` mixes casting with formatting, and remains available only as a migration bridge. Use `.to_string()` explicitly, or a codec such as `json.encode` when producing a wire format.
TE840The source value already has the requested type, so `as Type` communicates no new intent and performs no work. Remove the redundant cast expression.
TE841A numeric `cast` policy applies only to the conversion family it names — `.wrap` is defined only for integer-to-integer conversion, while `.trunc`/`.floor`/`.ceil`/`.nearest_even` convert floating-point values. Choose a compatible policy, or use `as?` when only exact values are accepted.
TE842`into::<T>()` requires a direct `impl From<Source> for T`, and `try_into::<T>()` requires a direct `impl TryFrom<Source> for T`. Zolo never invents a conversion chain through an intermediate type — implement the matching trait, or call the intended constructor explicitly.
TE843Generic `parse::<T>()` is a text operation: its receiver must be `str` or `bytes`, and `T` must be one of the numeric types supported by the core parser. Use a domain-specific decoder (such as `json.decode`) for structured data instead.
TE844`unsafe bitcast::<T>(value)` reinterprets representation bits rather than performing a numeric or domain conversion, so both types must be fixed-width numeric types with exactly the same bit width. Use `as?`, `cast::<T>(policy)`, `into`, or `try_into` to actually change the value instead.
TE845An `impl From<S>`/`TryFrom<S>` is only legal in the package that owns the source `S` or the destination type — otherwise two unrelated packages could define competing meanings for the same conversion. Zolo also rejects overlapping implementations and never searches conversion chains such as `A -> B -> C`.
TE846`as?` and `is` can only probe a primitive category or the declared name of a user type (generic types by their base name). A structural shape such as `[int]`, `{str: int}`, a record, a tuple, a union or `T?` has no runtime witness: probe the category (`as? array`, `is map`) or decode the value with `@derive(Deserialize)` to validate its elements.
TE970A tagged template `tag"…"` is not special syntax — it lowers to an ordinary call to a function named `tag`, and no such function is in scope.
TE976`parallel { … }` runs each top-level statement as its own concurrent task, so every statement in the block must be an expression that can become one.
TM100Compiler diagnostic TM100: `super` used outside a mixin body.
TM112Compiler diagnostic TM112: self-using mixin applied to a free function.
TM113Compiler diagnostic TM113: mixin application argument contract failure.
TM114Compiler diagnostic TM114: mixin result is incompatible with the decorated target.
TM115Compiler diagnostic TM115: explicit `super(...)` arguments do not match the target.
TM116Compiler diagnostic TM116: runtime mixin applied to a non-callable declaration.
Effects
16TE800A function performs an effect (`!io`, `!net`, `!fs`, ...) it did not declare in its signature.
TE801An effect was performed but no enclosing `handle` block handles it.
TE802A `handle` block tries to handle an operation the effect did not declare.
TE803A `handle` block is missing the implementation for one of the effect's declared operations.
TE804The handler references an operation name that does not exist on the effect.
TE805A function signature or handler references an effect the compiler cannot find.
TE806A `perform` call or handler operation does not match the effect's declared signature.
TE807`handle … with <handler_value>` uses a handler value that covers only some of an effect's operations. The error fires at the `with` site and names the missing operation(s).
TE808A `perform Effect::op(…)` call passed an argument whose type doesn't match the operation's declared parameter type.
TE809The summary form of TE800: instead of reporting each `perform` site, it collects every effect a boundary function actually needs and reports them all at the signature.
TE810A warning, not a build failure. A `handle` block using an explicitly annotated `handler<…>` value covers an effect the handled body never actually performs.
TE811A generic parameter is used both as a type parameter and as a row-variable tail in a `with` clause (`{Fs | e}`). A single name can't mean both a type and a set of extra effects.
TE812A `perform` targets an effect operation declared `multi` (resumable more than once). Multi-shot continuations are a VM-only capability today.
TE813A generic effect's type parameter couldn't be resolved at a `perform` site — neither the argument types nor a `with Effect<Concrete>` pin gave it a concrete type.
TE814`h` must be something whose type is `handler<…>`. If it resolves to anything else, there's no arm set to dispatch the performed operations to.
TE815A parameter typed as a plain function (`fn(...) -> T`, no `with` clause) promises purity — nothing it runs performs an effect the caller doesn't already know about. Passing a function that itself requires an effect there lets that effect escape completely undeclared, the same class of leak `TE802` blocks in the ordinary call direction.