Skip to content

Compiler diagnostics

Vertex takes diagnostics seriously. Every error has a title in plain English, notes about what the compiler knows, an actionable help: section, and where relevant a second span pointing at the conflicting declaration. This page is the index: each entry links the error code to an example and a one-line fix.

For the format philosophy, see Why Vertex: errors that teach.

The expression’s inferred type does not match what the context expects.

let n: Int = "hello"

To fix: convert the value or change the declaration. If you meant the declaration to match the value, drop the annotation and let the compiler infer.

You tried to reassign a let.

let x = 0
x = 1

To fix: change let to mutable let, or rebind with a new name: let y = 1.

The name is not in scope at the point of use.

debug grand_total

To fix: declare the binding or check the spelling. If the name lives in another module, add an import.

The call passes too many or too few arguments.

To fix: match the function’s parameter list, including any required named parameters.

A pattern form is not allowed in the context (for example, an OR pattern that binds different shapes).

To fix: split the pattern into separate arms, or use a wildcard and match on fields inside the arm body.

One or more variants of the matched type are not covered.

type Status { Active, Inactive, Archived }
fn label(s: Status): String {
match s {
Active => "active",
Inactive => "inactive",
}
}

To fix: add an arm for the missing variant, or a _ wildcard if you genuinely mean “anything else”. The compiler message lists the missing variants by name.

? only works on Result<T, E> expressions.

To fix: return a Result from the subexpression, or match on it directly if it is an Option.

E107: Error types don’t align in ? propagation

Section titled “E107: Error types don’t align in ? propagation”

The enclosing function’s error type does not match the inner expression’s error type.

To fix: convert with .mapError(...) before ?. See the error handling guide.

E108: Class does not implement all interface methods

Section titled “E108: Class does not implement all interface methods”

A type declared to implement an interface is missing one or more methods.

To fix: implement the missing methods listed by the compiler.

A name was declared twice in the same scope.

To fix: rename one of them, or delete the duplicate.

The spread operator ... inside a list literal was applied to a value that is not a List.

To fix: convert to a list first, or use a regular element expression.

The method name is not defined for the receiver’s type.

To fix: check the spelling, or consult the reference for the available methods on the type.

E136: @Test function must take no parameters

Section titled “E136: @Test function must take no parameters”

A function marked @Test has one or more parameters.

To fix: remove the parameters, or move the data into the test body.

A function marked @Test is in a non-test file.

To fix: rename the file to end in _test.vtx, or remove the annotation.

E138: Non-test module imports a test module

Section titled “E138: Non-test module imports a test module”

A non-test module cannot depend on a test module.

To fix: move the imported symbol to a non-test module, or remove the import.

The file starts with an annotation that the compiler does not recognise as a module-level annotation.

To fix: check the spelling against Annotations, or move the annotation to the appropriate declaration.

A module has more than one sharing annotation.

To fix: keep at most one of @WithSharing, @WithoutSharing, or @InheritedSharing.

A sharing annotation was called with parentheses or arguments.

To fix: remove the arguments. Sharing annotations are bare.

Deeper form of E101 with the original declaration’s location as a related span.

To fix: same as E101. Use mutable let on the original declaration.

A debug expression was left in source code.

To fix: remove it before shipping, or accept the warning if this is a vertex run script.

A local let was declared but its value is never read.

To fix: remove the binding, or prefix it with _ if the side effect of the RHS is what you wanted (let _ = compute()).

A function or closure parameter is never used.

To fix: remove the parameter, or prefix the name with _.

A binding was declared mutable let but never reassigned.

To fix: drop the mutable keyword.

A private (non-pub) top-level function is never referenced.

To fix: remove it, mark it pub if it is part of the public API, or prefix the name with _.

A private type declaration is never referenced.

To fix: remove it, or mark it pub.

A private const is never referenced.

To fix: remove it, or mark it pub const.

A sum-type variant of an internally-constructed type is never created in source.

To fix: remove the variant, or use it. If a future call site is planned, leave a comment; the warning stays until the variant is constructed.

A name imported selectively is never used.

To fix: remove the import, or use the name.

Prefix a name with _ to opt out of W002 through W007. This is the convention for intentionally-unused bindings.

fn process(_ignored: String): Int { 42 } // W003 suppressed
let _temp = expensive_computation() // W002 suppressed
fn _helper(): Void { } // W005 suppressed

The underscore convention does not apply to selective imports (W009): the imported name is defined elsewhere. Remove unused imports instead.