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.
71 / 126 with full explainers
Lint · 24
float-equality Comparing floats with `==` or `!=` Floating-point equality is imprecise. Use `~=` (adaptive tolerance), `!~=`, or `math.approx_eq_abs/_rel(...)`. For exact comparisons use the `decimal` type.
unused-variable Unused variable A `let`-bound variable or parameter is never read. Prefix the name with `_` to silence the lint intentionally.
unused-function Unused function A top-level function is never called and is not marked `pub`, `@test`, `@bench`, `@export`, an HTTP route, or `main`.
unused-import Unused import summary onlyAn imported name is never referenced in the file.
shadowed-variable Variable shadows outer binding summary onlyA `let` re-binds a name from an outer scope. Shadowing is sometimes intentional; rename one binding to silence the warning.
dead-code Dead code after terminal statement summary onlyCode after `return`, `break`, or `continue` is unreachable.
naming-convention Naming convention violation Functions/variables use `snake_case`; structs/enums/traits/effects use `PascalCase`.
must-use `@must_use` value discarded summary onlyA function or type annotated `@must_use` returned a value that the caller discarded. Bind it (`let _ = ...`) or consume it.
deprecated Use of deprecated item summary onlyA function annotated `@deprecated` was called. The annotation's message explains the replacement.
infinite-loop Infinite loop with no exit summary onlyA `loop`/`while true` block has no reachable `break`/`return`.
optional-typo Likely typo on optional access summary onlyA `Some(...)` / `None` / `?.` / `??` use that looks like a typo or misuse of the optional API.
non-exhaustive-match Non-exhaustive `match` A `match` over an enum does not cover every variant and has no wildcard `_` arm.
unreachable-pattern Unreachable `match` arm summary onlyA pattern can never match because an earlier arm already covers it.
max-line-length Line exceeds configured maximum length summary onlyConfigured via the project's lint config. Default is permissive; tighten in CI if you want hard limits.
max-nesting-depth Block nested deeper than allowed summary onlyDeep nesting hurts readability. Extract helpers or use early-return guard clauses.
max-parameters Function has too many parameters summary onlyLong parameter lists are a code-smell. Consider grouping related parameters into a struct.
max-function-length Function body exceeds configured length summary onlyBreak the function into smaller helpers.
unknown-repr Unknown `@repr(...)` policy summary onlyOnly `@repr(C)`, `@repr(packed)`, `@repr(transparent)`, and `@repr(zolo)` are recognized.
transparent-multi-field `@repr(transparent)` on multi-field struct summary only`transparent` only applies to single-field newtype-style structs.
layout-in-default-repr `@layout(...)` on default-repr struct summary only`@layout` only takes effect alongside an explicit `@repr`.
align-not-positive `@layout(align = ...)` must be positive summary onlyAlignment must be a positive power of two.
align-not-power-of-two `@layout(align = ...)` must be a power of two summary onlyHardware alignment rules require power-of-two values (1, 2, 4, 8, ...).
align-too-large `@layout(align = ...)` value too large summary onlyThe requested alignment exceeds the maximum the target platform supports.
size-not-positive `@layout(size = ...)` must be positive summary onlySize cannot be zero or negative.
Parse · 6
P0001 Unterminated string literal summary onlyThe lexer reached end-of-file (or end-of-line in some contexts) before finding the closing quote of a string literal.
P0002 Expected token The parser expected a specific token (e.g. `}`, `)`, identifier, type) but found something else. Usually a missing brace, paren, or punctuation.
P0003 Unexpected token summary onlyA token appeared where the grammar does not allow it — typically a stray symbol, a misspelled keyword, or a missing separator on the previous line.
P0004 Generic parse error summary onlyA parse-level error that did not match a more specific classifier. Read the diagnostic message for the precise cause.
P0005 HTML comment inside a tag summary onlyA `<!-- -->` 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.
TE139 Unclosed `<style>`/`<script>` raw text element `<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.
Type · 80
E0001 Type mismatch (legacy) summary onlyEquivalent to `TE001`. Emitted by the legacy message-pattern classifier when the new typeck did not attach a code.
E0002 Undefined variable (legacy) summary onlyLegacy alias for `TE100`.
E0003 Undefined function / not callable (legacy) summary onlyLegacy alias for `TE101`.
E0004 Cannot reassign (legacy) summary onlyLegacy alias for `TE004`. The variable was declared with `let`; use `let mut` to allow reassignment.
E0005 Undefined field (legacy) summary onlyLegacy alias for `TE102`.
E0006 Missing field summary onlyA struct literal omits one or more required fields.
E0007 Wrong number of arguments (legacy) summary onlyLegacy alias for `TE110`.
E0008 Return type mismatch summary onlyThe value being returned does not match the function's declared return type.
E0009 Duplicate declaration summary onlyA name (function, variable, field, variant) was declared twice in the same scope.
E0010 Unknown type summary onlyA type annotation refers to a type that the compiler cannot find.
TE001 `let` type mismatch The value assigned to a `let` binding does not satisfy the declared type annotation.
TE002 `const` type mismatch summary onlyThe value assigned to a `const` binding does not satisfy the declared type annotation.
TE003 `const` value not a compile-time constant summary only`const` requires a constant-foldable expression. Use `let` for runtime values.
TE004 Cannot reassign immutable binding `let` bindings are immutable by default. Use `let mut x = ...` to allow reassignment, or use a fresh `let` shadow.
TE005 Compound assignment on non-numeric summary onlyOperators like `+=`, `-=`, `*=` require both sides to be numeric (or strings for `+=`).
TE006 Multi-return arity mismatch (too few) summary onlyThe function declared a tuple return but the actual `return` statement provides fewer values.
TE007 Multi-return arity mismatch (too many) summary onlyThe function returns more values than its declared single-value return type can hold.
TE008 Array element type mismatch summary onlyAn array literal mixes incompatible element types; arrays are homogeneous.
TE009 Arithmetic on incompatible types summary onlyBinary arithmetic requires both operands to be numeric and (in strict mode) the same numeric type.
TE100 Undefined variable The name is not declared in any enclosing scope. The compiler attaches a "did you mean?" suggestion when a similar name exists.
TE101 Calling a non-function value summary onlyThe callee in a function-call expression is not a callable type.
TE102 Struct has no such field summary onlyThe struct does not declare this field. "Did you mean?" suggestions are attached for near-matches.
TE103 Unknown type name summary onlyA type annotation or enum-variant field references a type the compiler cannot resolve.
TE104 No such method The receiver type does not have a method with this name. Check spelling, imports, and trait visibility.
TE105 Stdlib module used without `use std::…` A 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.
TE107 Missing field in struct construction A 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.
TE108 Cannot derive `Default`: field has no default A 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.
TE109 Cannot infer field type from its default A 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`).
TE110 Method call arity mismatch The number of arguments passed does not match the function's parameter count.
TE111 Method call argument type mismatch An argument's type does not match the corresponding parameter's declared type.
TE112 `using`-embedded field is ambiguous Two 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.
TE113 `using` field must embed a struct A 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.
TE114 Enum with numeric discriminants cannot be generic An 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.
TE115 Discriminant does not fit the backing type A 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()`.
TE116 Duplicate discriminant value Two 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.
TE117 `@stable` enum requires an explicit discriminant Under `@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.
TE118 Discriminant must be an integer constant A 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.
TE119 `@flags` enum must be flat and non-generic An `@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.
TE120 Flag value must be a power of two or a composite Each `@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.
TE121 Flag value does not fit the backing type A flag's value is out of range for the enum's backing type — `enum: u8` bit-flags top out at `255` (bit 7).
TE122 Two flags occupy the same bit Two single-bit flags in the same `@flags` enum resolved to the same bit, usually because both were given the same explicit value.
TE123 No such field in destructuring pattern A destructuring pattern — `let Struct { … } = expr`, an anonymous `let { … }`, a parameter pattern, or a struct-destructuring assignment — names a field the struct doesn't have.
TE124 `let … else` block must diverge The `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.
TE125 Refutable pattern in `let` requires `else` The 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.
TE126 Cannot infer the struct behind `let { … }` An 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.
TE127 Parameter pattern struct does not match its annotation A named struct pattern in parameter position (`fn f(StructName { … }: T)`) names a different struct than the parameter's own type annotation.
TE128 Spread source must be a struct or record A 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.
TE129 Tuple-assignment value-count mismatch A tuple-destructuring assignment (`(a, b, c) = expr`) has a different number of targets than `expr` has values.
TE130 Destructuring assignment only supports `=` Compound operators (`+=`, `-=`, …) have no per-element meaning when the left-hand side is a whole pattern, and `..` spread makes no sense as an assignment target.
TE131 Named-argument call cannot be reordered A 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.
TE132 Invalid `_` placeholder The `_` 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.
TE133 Unknown enum variant A 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.
TE136 Cannot infer the enum for a `.Variant` shorthand The `.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.
TE137 Unknown variant in a `.Variant` shorthand The `.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.
TE134 VM-prelude name has no native implementation The 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.
TE135 Unknown name has no native binding A 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.
TE201 Strict mode: variable needs annotation summary onlyStrict typing requires every `let`/`const` to have an explicit type annotation.
TE202 Strict mode: parameter needs annotation summary onlyStrict typing requires every function parameter to have an explicit type.
TE301 Generic type argument count mismatch summary onlyThe number of type arguments supplied does not match the generic's declared parameter count.
TE302 Unknown trait summary onlyA trait bound, `impl` block, or `where` clause references a trait the compiler cannot find.
TE730 `@()` interpolation outside a declaration value `@(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.
TE731 Runtime `children` on `<style>` requires `global` A `<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.
TE732 CSS interpolation value has a non-serializable type A `@()` 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 `@()` glued to adjacent CSS value text `@()` 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 Malformed `:global()` — empty or nested `: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.
TE735 Scoped selector matches no element of the component A 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.
TE736 `<style>` outside a component has no scope A 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.
TE737 `@()` needs a root element to carry its value Every `@()` 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.
TE738 Unknown CSS property A 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.
TE820 Type does not implement a required trait A generic function is called with a type argument that doesn't implement a trait required by one of its bounds.
TE821 Operator requires a trait bound on the type parameter An 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.
TE822 Trait does not exist A bound in a function signature names a trait the compiler doesn't recognise.
TE823 Operator requires the concrete type to implement a trait An 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.
TE824 Invalid qualified trait path Qualified 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.
TE825 Incomplete trait impl: missing required method An `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.
TE826 Collection method on un-unwrapped `Result`/`Option` A collection method (`each`, `filter`, `len`, …) was called on a `Result` or `Option` wrapper directly. Unwrap it first with `?>`, `?`, or `.unwrap()`.
TE827 `?.` null-safe chain on `Result`/`Option` `?.` 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 Type is not iterable `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.
TE970 Tagged template has no matching tag function A 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 Non-expression statement inside `parallel { }` `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.
Effects · 15
TE800 Missing effect declaration summary onlyA function performs an effect (`!io`, `!net`, `!fs`, ...) it did not declare in its signature.
TE801 Unhandled effect summary onlyAn effect was performed but no enclosing `handle` block handles it.
TE802 Effect not declared by handler summary onlyA `handle` block tries to handle an operation the effect did not declare.
TE803 Handler missing operation summary onlyA `handle` block is missing the implementation for one of the effect's declared operations.
TE804 Unknown operation in handler summary onlyThe handler references an operation name that does not exist on the effect.
TE805 Unknown effect summary onlyA function signature or handler references an effect the compiler cannot find.
TE806 Effect arity / signature mismatch summary onlyA `perform` call or handler operation does not match the effect's declared signature.
TE807 Handler value coverage is incomplete `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).
TE808 `perform` argument type mismatch A `perform Effect::op(…)` call passed an argument whose type doesn't match the operation's declared parameter type.
TE809 Function performs effects it does not declare The 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.
TE810 Handler covers an effect the body never performs A warning, not a build failure. A `handle` block using an explicitly annotated `handler<…>` value covers an effect the handled body never actually performs.
TE811 Generic parameter bound as both type and row variable A 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.
TE812 Multi-shot effect is not supported on the native backend A `perform` targets an effect operation declared `multi` (resumable more than once). Multi-shot continuations are a VM-only capability today.
TE813 Cannot infer a type argument for an effect operation A 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 `handle … with h` requires a handler value `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.