Skip to main content
GLua ships with built-in diagnostics that catch common mistakes in Garry’s Mod Lua. This page lists every rule, grouped by the area it covers. Each rule has two names, and they are not the same thing:
  • a diagnostic code such as net-payload-mismatch, shown in the Problems panel and used by inline suppressions
  • a settings key such as netReadWriteMismatch, used in .glua.json and in VS Code settings
Severity accepts error, warning, information, hint or off. Every rule has its own section below, and the code shown in the Problems panel links straight to it. glua rules lists the same catalogue in the terminal, and SARIF output carries the same links into GitHub code scanning.

Globals

undefined-global

undefinedGlobal · default warning A global that is neither a known GMod API member nor assigned anywhere in the workspace — usually a typo, sometimes a dependency this project does not declare. Existence checks are respected, so the usual way of depending on an optional addon does not trigger it:
For a hard dependency, declare it under globals rather than turning the rule off — that keeps the check working for real typos.

global-write

globalWrite · default off Writing to a global instead of declaring a local, which leaks the name into _G where any other addon can collide with it. Noisy by design in code that uses a single global table on purpose, so it ships off.

unused-local

unusedLocal · default hint A local declared but never read. Names starting with _ are exempt, which is the conventional way to say a value is deliberately ignored.

Realms

realm-violation

realmViolation · default warning A call to API that cannot exist in this file’s realm — a serverside-only function in a clientside file, or the reverse. The call is nil at runtime, so this is an error waiting to happen rather than a style question. Reported as information instead when the realm was inferred from a cl_/sv_ filename prefix, since that is a convention rather than a guarantee: plenty of addons include a cl_ file on both realms. A directory such as lua/autorun/server/ is treated as certain.

Net messages

net-unregistered

netMessage · default warning net.Start on a message never passed to util.AddNetworkString. Fails at runtime. A quick fix inserts the registration.

net-never-dispatched

netMessage · default warning A net.Start block that never calls net.Send, net.Broadcast or net.SendToServer, so the message is built and dropped. Silent at runtime, which is what makes it worth reporting.

net-never-received

netMessage · default warning A message that is sent but has no net.Receive anywhere in the workspace.

net-never-sent

netMessage · default warning A net.Receive for a message nothing ever sends — usually a rename that happened on one side only.

net-payload-mismatch

netReadWriteMismatch · default warning The net.Write* sequence in the sender does not match the net.Read* sequence in the handler. Reading a string where an integer was written does not error; it returns nonsense.

Hooks and timers

unknown-hook

unknownHook · default information A hook name that is neither documented nor fired anywhere in the workspace. Quick fixes offer the closest known names by edit distance.

duplicate-hook-identifier

duplicateIdentifier · default warning Two hook.Add calls with the same event and identifier in overlapping realms. The second silently replaces the first, so one of the two never runs.

duplicate-timer-name

duplicateIdentifier · default warning Two timer.Create calls with the same name in overlapping realms, with the same consequence: the second replaces the first.

API calls

deprecated

deprecated · default warning Use of API the wiki marks deprecated or removed. The message includes the documented replacement.

argument-count

argumentCount · default warning The wrong number of arguments, checked against every documented call form. Skipped for the Lua standard library, whose documented signatures are not precise enough to check against — table.insert is documented only in its three-argument form, and the two-argument form is everywhere in real code.

argument-type

argumentType · default warning An argument whose inferred type cannot match the documented parameter. Only fires when no documented overload accepts what was passed.

Performance

perf-hot-path

perfHotPath · default warning Expensive work reached from something the engine runs every frame or tick — a render hook, ENT:Think, a timer.Create that repeats forever at 0.5s or less. The message names the chain of functions that reaches it, so a finding four calls and two files away from its hook still explains itself. Calls behind a CurTime() guard, a nextThink-style field, or a one-time if not x then gate are skipped, since those already rate-limit themselves. Full description.

Dead code

unused-function

unusedFunction · default off A function this workspace defines and never calls, references or registers. Methods defined with a colon, scripted class hooks and anything extending an API library are exempt, since those are reached through a value rather than a name. Off by default: an addon meant to be used by other addons is full of these on purpose. glua doctor lists them either way.

Files

missing-addcsluafile

missingAddCSLuaFile · default warning A clientside file that is included but never sent with AddCSLuaFile, so clients never receive it. Directories the engine networks itself are skipped. A quick fix inserts the missing call.

missing-asset

missingAsset · default off A material, model or sound path that does not exist. Missing content never raises a Lua error — it renders as the checkerboard, the error model, or silence — which is exactly why a typo here can survive a long time. Requires workspace.gamePath, and off by default on purpose: content mounted from the Workshop or a separate content pack is invisible from here, so on a typical server most findings would be wrong. Turn it on only if every asset you reference ships in this repository.

Suppressions

unused-suppression

unusedSuppression · default hint A -- glua-ignore or -- glua-disable comment that never silenced anything. A suppression outlives the finding it was written for: the code gets fixed, the comment stays, and from then on it silently covers whatever appears on that line next. A misspelled rule name looks exactly like working protection, and so does one for a rule that has since been turned off. Only reported for files that parse. A parse error stops most rules from running, so every directive in the file would read as dead.
The local is read, so nothing is being suppressed and the comment is dead — it outlived the finding it was written for. A misspelled rule name produces the same report, which is the point: unusedLocal where unused-local belonged silences nothing and looks like it does.

Syntax

Always reported as errors, and not configurable.

syntax

The file does not parse. Formatting is disabled for the file while this is present, since reformatting a file the parser could not read would lose code.

compound-assignment

x += 1 is not valid Lua, however much it looks like it should be. A quick fix rewrites it as x = x + 1.

Setting severity

Tune rules in .glua.json using the settings key given under each rule above. Each accepts error, warning, information, hint or off.
Omitted rules keep their built-in default, so you only list what you want to change. The hosted JSON schema validates these keys as you type — an unknown key is flagged in the editor.
Do not use the diagnostic code as a settings key. "net-payload-mismatch": "error" is not a valid entry; the key is netReadWriteMismatch. Codes are for the Problems panel and for -- glua-ignore.