Skip to content

All Diagnostics

Complete reference of every diagnostic code. For an introduction to how diagnostics work and how to configure them, see the Diagnostics guide.

Warning severity

CodeDescription
deprecatedUsage of @deprecated symbols (flavor-aware: suppressed when the API is still live in a flavor the addon targets; see Flavor Filtering)
discard-returnsIgnoring @nodiscard return values
type-mismatchArgument type vs @param mismatch (including generic type arguments, e.g. Container<number> vs Container<boolean>, and string-literal unions, e.g. "x" against "A"|"B"|"C")
return-mismatchReturn type vs @return mismatch
field-type-mismatchField assignment vs @field type mismatch
assign-type-mismatchReassignment vs @type mismatch
generic-constraint-mismatchGeneric argument doesn't satisfy a class, alias, or keyof constraint
param-constraint-mismatchMethod called when the receiver's @requires type-param constraint isn't satisfied
missing-parameterMissing required function arguments
redundant-parameterExtra function arguments
missing-return-valueReturn with fewer values than @return
redundant-return-valueReturn with more values than @return
grouped-return-mismatchReturn values don't match any tuple-union @return case
missing-returnFunction missing return statement
undefined-globalReference to unresolved global name
undefined-fieldReading a nonexistent field on a @class, a module-private table (local p = {}), or a string value (("x").foo, checked against the string library)
need-check-nilField/method access on possibly-nil value (off by default)
nil-indexBracket-indexing a table with a possibly-nil key (off by default)
nil-table-keyTable key type annotation includes nil (table<string?, V>)
access-privateAccessing @field private from outside
access-protectedAccessing @field protected from outside hierarchy (also _-prefixed fields when implicitProtectedPrefix is enabled)
duplicate-indexDuplicate keys in table constructors
redundant-valueExtra values in assignments
unbalanced-assignmentsMore variables than values in assignments, including when a function call returns fewer values than variables assigned
missing-fieldsMissing required fields when constructing @class tables
undefined-doc-classUndefined class name in @class Foo: Parent
undefined-doc-nameUndefined type name in annotations
undefined-doc-param@param name not matching function parameters
duplicate-doc-paramDuplicate @param annotations
duplicate-doc-fieldDuplicate @field annotations
duplicate-doc-aliasDuplicate @alias declarations
doc-field-no-class@field on a non-@class table
doc-func-no-functionFunction-level annotation (@param, @return, etc.) not attached to a function definition
circle-doc-classCircular @class inheritance chains
malformed-annotationUnknown or incomplete ---@ annotations
multi-return-projectionreturns<F> discards extra return values from F
builds-field-not-self@builds-field method uses @return ClassName instead of @return self
unknown-diag-codeUnknown code in @diagnostic directives
duplicate-constructorMultiple @constructor on a single class
constructor-return@constructor with return other than @return self
count-down-loopFor-loop step direction doesn't match start/end
wrong-flavor-apiAPI not available in all declared flavors
redundant-class-genericMethod redeclares class-level @generic
cannot-callCalling a value whose type is not callable
invalid-opOperator applied to incompatible types (e.g. + on strings instead of ..) (off by default)
create-globalImplicit global creation
invalid-class-parentInheriting from a non-table type (number, string, literals, etc.)
mixed-enum-values@enum with mixed number/string values or unsupported value types
unknown-callback-eventEvent name passed to a callback registry that was never declared via GenerateCallbackEvents (off by default)
class-shadows-builtinA workspace @class with its own @fields reuses a built-in WoW API class name

Hint severity

CodeDescription
return-self-class-nameMethod uses @return ClassName instead of @return self
unused-localUnreferenced local variables
unused-functionUnused function definitions (off by default)
unused-varargFunction declares ... but never uses it (off by default)
redefined-localSame-scope local variable redefinition
shadowed-localLocal variable shadows an outer-scope variable
inject-fieldSetting undeclared fields on @class tables
duplicate-set-fieldSetting an already-set field on @class tables
unreachable-codeCode after return
code-after-breakCode after break
incomplete-signature-docPartial @param/@return annotations (off by default)
missing-param-annotationNon-file-local function parameter has no @param (off by default)
missing-return-annotationNon-file-local function returns a value but has no @return (off by default)
empty-blockEmpty control flow body
redundant-returnBare return at end of function
trailing-spaceLine ends with whitespace
not-precedencenot x <cmp> y is (not x) <cmp> y
redundant-oror where left side is always truthy (RHS is dead code) (off by default)
redundant-andand where left side is always falsy (RHS is dead code) or always truthy (operator is a no-op) (off by default)
redundant-conditionif/elseif/while condition is provably constant (off by default)
implicit-nil-returnBare return in function with optional @return (off by default)
unknown-param-typeParameter type can't be inferred (off by default)
unknown-return-typeReturn value has no resolvable type (off by default)
unknown-local-typeLocal assignment has unknown type (off by default)
unknown-field-typeField assignment has unknown type (off by default)

missing-param-annotation / missing-return-annotation

Flag functions that lack @param / @return documentation. Both are off by default. Enable them when you want every public function fully documented:

json
{
  "diagnostics": {
    "enable": ["missing-param-annotation", "missing-return-annotation"]
  }
}

missing-param-annotation fires once per source parameter without a matching @param (the implicit self of a colon method and the conventional _ throwaway are skipped). missing-return-annotation fires once on a function whose body returns a value but has no @return.

Scope: only functions reachable beyond their file are checked. Checked:

  • ✅ Global functions: function GlobalFn() end
  • ✅ Methods/fields on a global table: function GlobalApi.Run() end
  • ✅ Methods/fields on a @class: function Widget:SetValue() end
  • ✅ Methods/fields on the addon namespace: function ns.Module.Process() end
  • ✅ Methods on a local table that is attached to the addon namespace (local M = {}; function M.foo() end; ns.M = M)

Skipped:

  • local function definitions
  • ❌ Anonymous function literals (local f = function() … end, callback arguments)
  • ❌ Bare function foo() that reassigns a forward-declared local foo
  • Methods on a file-private local table (local cache = {}; function cache.get() end) that never escapes the file

The escape test for table methods reuses the workspace global scan: a method is "reachable" exactly when the language server registers it as a cross-file symbol, so this stays consistent with go-to-definition and find-references.

This differs from incomplete-signature-doc, which fires only when a signature is partially annotated (and regardless of where the function lives). missing-*-annotation fires even on a completely undocumented function, but only for non-file-local ones. The two can be enabled together; a partially-annotated global will then report under both.

redundant-condition

Flags if/elseif/while/repeat...until conditions that are provably always true or always false. Detected patterns:

  • Always-truthy/falsy type: the condition's resolved type is guaranteed truthy (e.g. table, number) or guaranteed falsy (nil).
  • Negation of a constant: not expr where expr is itself always truthy or always falsy (e.g. if not tbl where tbl is a table).
  • Type-incompatible equality: ==/~= between values whose types can never match at runtime (e.g. num == "hello", nonNilVar == nil).
  • Literal-union miss: x == "c" where x is typed as "a"|"b" and "c" is not a member.
  • Two-literal comparison: both sides are concrete literals (e.g. 1 == 2, "a" == "a", 3 < 2).
  • Self-comparison: x < x or x > x (always false; NaN-safe). <=/>=/==/~= self-comparisons are excluded because NaN breaks them.
  • Redundant type() guard: type(x) == "number" where x is already known to be a number (always true) or can never be a number (always false).

Loop idioms (while true, repeat...until false) are not flagged. Conditions referencing variables reassigned inside loops are suppressed to avoid false positives.

unused-function

Flags function definitions that are never referenced anywhere in the workspace. Covers both top-level global functions and methods defined on tables (e.g. function NS.Method()).

What counts as "used":

  • Called directly via call_resolutions (handles deep type inference, self-calls, etc.)
  • Referenced as a value (e.g. passed as a callback, stored in a variable) - detected via field-access token resolution with inheritance

What is skipped (not flagged):

  • Functions whose name starts with _ (convention for intentionally unused)
  • Functions defined in library files (directories marked with library in .wowluarc.json)
  • Interface methods: if 2+ distinct tables define the same method name, the method is assumed to be a framework callback pattern (duck-typing dispatch)
  • Inherited methods: if a parent class's field is referenced, child overrides are also considered used

Cross-file behavior:

This diagnostic requires a multi-file workspace scan. It compares definitions from all files against references from all files. In single-file mode (e.g. evaluate), only per-file unused functions are detected.

TOC file diagnostics

These diagnostics apply to .toc files only. See the TOC Files guide for details.

CodeSeverityDescription
toc-missing-interfaceWarningRequired ## Interface: field is missing
toc-duplicate-headerWarningSame header key appears more than once
toc-unknown-headerHintHeader not in the known catalog and not X-*
toc-invalid-interfaceErrorInterface value is not a valid numeric version
toc-nonexistent-fileWarningReferenced file does not exist on disk
toc-invalid-valueWarningValue doesn't match expected format

LuaLS compatibility aliases

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

Diagnostic codes that LuaLS defines but wowlua_ls has no equivalent for (e.g. lowercase-global, cast-type-mismatch, unused-label) are accepted silently in ---@diagnostic directives - they suppress nothing here, but won't trip unknown-diag-code, so a project that also runs LuaLS can keep its suppressions without noise.