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.

E162: global fn signature references a non-global user type

Section titled “E162: global fn signature references a non-global user type”

A global function exposes a parameter or return type that is not itself global (or extern, or a built-in primitive/container). Apex would reject this at deploy time; Vertex rejects it at compile time.

To fix: mark the referenced type as global, or change the signature to use a global-accessible type. See Visibility for the full rule set.

E163: global type variant field references a non-global user type

Section titled “E163: global type variant field references a non-global user type”

A global type exposes a variant field whose declared type is not itself global. Every type reachable through a global type’s public surface must be global too.

To fix: mark the referenced type as global, or change the field’s declared type.

E164: global const resolved type references a non-global user type

Section titled “E164: global const resolved type references a non-global user type”

A global const’s compile-time type references a user-defined type that is not global.

To fix: mark the referenced type as global, or drop the global modifier on the constant.

E165: Option, Result, tuple, Request, or Response in a global signature

Section titled “E165: Option, Result, tuple, Request, or Response in a global signature”

Option<T>, Result<T, E>, tuples, and the vertex.http types Request / Response emit as public inner classes (or are part of the public Vtx_Http runtime) and cannot cross namespace boundaries. They are forbidden in any global signature position.

To fix: unwrap the value at the boundary, or define a user-level global type that models the same shape. For REST handlers specifically, use fn or pub fn rather than global fn — the enclosing @RestResource class is already auto-promoted to global.

E166: global declaration in an @IsTest module

Section titled “E166: global declaration in an @IsTest module”

Apex test classes must be private, which directly contradicts a global declaration (which requires the enclosing class to be global).

To fix: move the global declaration to a non-test module, or remove the global modifier.

E170: @RestResource missing or malformed urlMapping

Section titled “E170: @RestResource missing or malformed urlMapping”

@RestResource requires a urlMapping: named argument whose value is a string literal.

To fix: write @RestResource(urlMapping: "/path") with a string-literal path.

@Get/@Post/@Put/@Patch/@Delete handlers must have the shape fn(req: Request, <captures: String>...): Response — first parameter is Request, return type is explicitly Response, and any additional parameters are String.

To fix: adjust the handler’s signature to match the rule. Import Request and Response from vertex.http.

E172: Verb annotation outside a @RestResource module

Section titled “E172: Verb annotation outside a @RestResource module”

@Get/@Post/etc. are only valid inside a module marked with @RestResource(urlMapping: "/...").

To fix: add @RestResource(urlMapping: "/your-path") at the top of the file, or remove the verb annotation.

The urlMapping argument must start with /, must not be empty, and must not contain * — Vertex appends the Apex wildcard at codegen.

To fix: use @RestResource(urlMapping: "/base/path") without a trailing *. Add per-verb path suffixes like @Get("/{id}") for nested URLs.

E174: Malformed path pattern in a verb annotation

Section titled “E174: Malformed path pattern in a verb annotation”

The optional path-suffix argument on @Get/etc. must start with /, must not contain *, and must have balanced {name} captures with valid identifier-style names.

To fix: rewrite the pattern. Examples: @Get("/{id}"), @Get("/{id}/contacts/{contactId}"), @Get("/active").

Two handlers on the same verb cannot both match the same concrete URI. Patterns conflict when they have the same number of segments AND the same literal-vs-capture shape at every position.

To fix: make one pattern more specific by adding a literal segment, or remove the duplicate handler.

E176: Path captures and handler parameters do not align

Section titled “E176: Path captures and handler parameters do not align”

Every {name} capture in a verb annotation must correspond to a same-named String parameter on the handler function, in declaration order.

To fix: rename the handler parameter to match the capture, or rename the capture to match the parameter.

E178: @RestResource module has no handlers

Section titled “E178: @RestResource module has no handlers”

A module annotated with @RestResource(urlMapping: "/...") must declare at least one handler function marked with a verb annotation.

To fix: add an @Get/@Post/etc. handler, or remove the @RestResource annotation.

E179: Cannot run a @RestResource module locally

Section titled “E179: Cannot run a @RestResource module locally”

REST resources are dispatched by the Salesforce REST framework — there is no local execution surface. vertex run is not a meaningful command for a @RestResource module.

To fix: deploy the module with vertex build + sf project deploy start, then invoke the endpoint over HTTP.

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.