server notes

Fixing a prop/NPC spawn-flood issue on my Garry's Mod server

Some notes on a stability problem I ran into while running Groszkowo, my Garry's Mod (Source engine) server — how I found it, reproduced it on a separate test instance, and patched it.

by Piotr stack: Garry's Mod, Source engine, SteamCMD, ULX status: fixed

Background

I run and admin Groszkowo, a small Garry's Mod sandbox server. Anyone who's run a sandbox server knows the usual headache: players spawning way too many props or NPCs and tanking the tickrate until the server basically stops responding. I'd set limits for this a while ago and mostly forgot about it, until it happened again.

[20:41:03] player spawned prop (count: 340) [20:41:04] tickrate dropped: 66 → 9 [20:41:06] server not responding

What was actually wrong

Garry's Mod controls this with convars like sbox_maxprops, sbox_maxnpcs, sbox_maxballoons, set in server.cfg. Going through my config, I found I'd typo'd the NPC limit convar at some point — it was set under a name close to, but not exactly, what the engine reads. So it never actually applied, and the server had been running on the engine's default (much higher) limit this whole time without me noticing.

Not a glamorous "exploit," but the effect is the same as a resource-exhaustion issue caused on purpose — the server falls over either way, so I treated it the same: reproduce it properly, then fix it, then check the fix actually holds.

Reproducing it safely

Before touching the live server, I spun up a separate local instance with SteamCMD and copied the config over there. Wrote a small script to spawn props/NPCs in a loop so I could see exactly where the tickrate starts dropping instead of guessing at a "safe" number.

local test run (not the live server):
sbox_maxprops   tried: 50 / 100 / 150 / 200
  -> tickrate drops noticeably past ~120 props/player

sbox_maxnpcs    convar name was wrong in server.cfg — had zero effect
  -> after fixing the name, limit applied immediately on restart

The fix

[after fix] spawn blocked: per-player limit reached [after fix] tickrate stable: 66

Checking it actually holds

Ran the same test script against the patched config on the test instance first. Spawn got blocked before the tickrate moved at all, and hammering it with repeated requests didn't get around the cap. Only pushed the change to the live server after that.


Why I'm writing this down

Same approach applies outside of GMod — I do the same thing (find the issue, reproduce it somewhere isolated, fix it, re-test) when looking at server-side exploit patterns in Roblox Lua for the admin/chat/NPC systems I build there, so I can design them to hold up better from the start.

This is meant as a record of defensive work on my own projects, not a how-to for breaking someone else's server — so I've left out exact payloads and anything about systems that are still running unpatched elsewhere.