Skip to content

Diagnostics

wowlua-ls ships 55+ diagnostics covering type safety, annotation correctness, code quality, and WoW-specific checks. Each one is individually suppressible and configurable.

How diagnostics work

Diagnostics run automatically as you type. They're grouped by severity:

  • Warning — likely a bug or an annotation problem
  • Hint — code quality suggestions, unused variables, style issues

Each diagnostic has a code (like type-mismatch or unused-local) that you use to suppress or configure it.

Suppressing diagnostics

Inline

Suppress a diagnostic on the same line by appending disable-line at the end:

lua
local unused = computeSomething() ---@diagnostic disable-line: unused-local

Previous line

lua
---@diagnostic disable-next-line: unused-local
local unused = computeSomething()

Per-block

lua
---@diagnostic disable: undefined-global
MY_GLOBAL = true
OTHER_GLOBAL = false
---@diagnostic enable: undefined-global

Per-project

In .wowluarc.json:

json
{
  "diagnostics": {
    "disable": ["inject-field", "unused-local"]
  }
}

LuaLS compatibility aliases

For compatibility with LuaLS suppress comments, these aliases are accepted:

AliasMaps to
invisibleaccess-private, access-protected
param-type-mismatchtype-mismatch
return-type-mismatchreturn-mismatch

Type safety diagnostics

These catch type errors — the most valuable diagnostics for finding real bugs.

type-mismatch Warning

Argument type doesn't match the function's @param annotation:

lua
---@param name string
function greet(name) end

greet(42) -- type-mismatch: expected string, got number

return-mismatch Warning

Return type doesn't match the function's @return annotation:

lua
---@return string
function getName()
    return 42 -- return-mismatch
end

field-type-mismatch Warning

Assignment to a field doesn't match its @field type:

lua
---@class Config
---@field name string

---@type Config
local cfg = {}
cfg.name = 42 -- field-type-mismatch

assign-type-mismatch Warning

Reassignment doesn't match the variable's @type annotation:

lua
---@type string
local x = "hello"
x = 42 -- assign-type-mismatch

generic-constraint-mismatch Warning

Generic argument doesn't satisfy the class constraint:

lua
---@class Box<T: number|string>

---@type Box<boolean> -- generic-constraint-mismatch
local b = {}

need-check-nil Warning Off by default

Field/method access on a possibly-nil value:

lua
---@param name string?
function greet(name)
    print(name:upper()) -- need-check-nil
end

Enable in .wowluarc.json: "diagnostics": { "enable": ["need-check-nil"] }

grouped-return-mismatch Warning

Return values don't match any declared tuple-union case:

lua
---@return (string, number) | (nil, nil)
function example()
    return "hello", nil -- grouped-return-mismatch
end

Argument diagnostics

missing-parameter Warning

Required argument not provided:

lua
---@param a number
---@param b number
function add(a, b) end

add(1) -- missing-parameter: b

redundant-parameter Warning

Extra arguments beyond what the function accepts:

lua
---@param x number
function single(x) end

single(1, 2) -- redundant-parameter

Return diagnostics

missing-return-value Warning

Return with fewer values than declared:

lua
---@return string, number
function getInfo()
    return "hello" -- missing-return-value
end

missing-return Warning

Function with @return but no return statement on some paths:

lua
---@return string
function getName()
    if self.name then
        return self.name
    end
    -- missing-return (falls off without returning)
end

redundant-return-value Warning

Returning more values than declared:

lua
---@return string
function getName()
    return "hello", 42 -- redundant-return-value
end

implicit-nil-return Hint Off by default

Bare return in a function with all-optional @return types:

lua
---@return string?
function maybeName()
    if not self.loaded then return end -- implicit-nil-return
    return self.name
end

Global and field diagnostics

undefined-global Warning

Reference to an unresolved global name:

lua
print(MyUnknownGlobal) -- undefined-global

Suppress with globals.read in .wowluarc.json for known external globals.

undefined-field Warning

Accessing a field that doesn't exist on a @class:

lua
---@class Player
---@field name string

---@type Player
local p = {}
print(p.level) -- undefined-field

inject-field Hint

Setting a field not declared on a @class:

lua
---@class Player
---@field name string

---@type Player
local p = {}
p.level = 10 -- inject-field

create-global Hint

Creating a global variable (assignment or function definition without local):

lua
MyGlobal = true -- create-global
function GlobalFunc() end -- create-global

Suppress with globals.write in .wowluarc.json.

missing-fields Warning

Missing required fields when constructing a @class table:

lua
---@class Config
---@field name string
---@field debug boolean

---@type Config
local cfg = { name = "test" } -- missing-fields: debug

Annotation diagnostics

undefined-doc-class Warning

Undefined parent in @class Foo : Parent:

lua
---@class Child : NonexistentParent -- undefined-doc-class

undefined-doc-name Warning

Undefined type name in any annotation:

lua
---@param x NonexistentType -- undefined-doc-name
function foo(x) end

undefined-doc-param Warning

@param name doesn't match any function parameter:

lua
---@param nme string -- undefined-doc-param (typo: should be 'name')
function greet(name) end

duplicate-doc-param / duplicate-doc-field / duplicate-doc-alias Warning

Duplicate annotation declarations.

circle-doc-class Warning

Circular inheritance chain:

lua
---@class A : B
---@class B : A -- circle-doc-class

malformed-annotation Warning

Unknown or incomplete ---@ annotation.

unknown-diag-code Warning

Unknown code in @diagnostic directives.

Code quality diagnostics

unused-local Hint

Unreferenced local variable.

unused-function Hint

Unused function definition.

redefined-local Hint

Same-scope local variable redefinition.

unreachable-code / code-after-break Hint

Code after return or break.

deprecated Warning

Usage of a symbol marked @deprecated.

discard-returns Warning

Ignoring the return value of a @nodiscard function.

not-precedence Hint

not x < y parses as (not x) < y, which is almost certainly not what you meant.

count-down-loop Warning

Numeric for-loop step direction doesn't match start/end:

lua
for i = 10, 1 do -- count-down-loop: needs step -1
    print(i)
end

Style diagnostics

empty-block Hint

Empty if/while/for/repeat body. Suppressed if the body contains a comment.

redundant-return Hint

Bare return as the last statement of a function's top block.

trailing-space Hint

Line ends with whitespace.

WoW-specific diagnostics

wrong-flavor-api Warning

API call not available in all declared project flavors. See Flavor Filtering.

access-private / access-protected Warning

Accessing a private or protected field from outside its visibility scope.

Strict typing diagnostics Hint

These are off by default. They fire when the LS can't determine a type — enable them to find gaps in your annotation coverage:

CodeFires when
unknown-param-typeFunction parameter type can't be inferred
unknown-return-typeReturn value has no resolvable type
unknown-local-typelocal x = expr where expr type is unknown
unknown-field-typeField assignment with unknown RHS type

Enable in .wowluarc.json:

json
{
  "diagnostics": {
    "enable": ["unknown-param-type", "unknown-return-type"]
  }
}