Fix: AMX_ERR_STACKERR / Run time error 3: stack error

May 21, 2025 Daemon666 8 min read 228 görüntülenme

A plugin throws Run time error 3 and either spams your log or crashes a feature mid-round. Error 3 is AMX_ERR_STACKERR — the Pawn virtual machine's stack collided with its heap. It is not random: it means a plugin tried to reserve more temporary memory than the VM has, and the fix is almost always to move a large buffer off the stack. Here is how to read it, locate the function, and repair the source.

1. Read the full log line first

Open addons/amxmodx/logs/ and find the entry. Unresolved, it looks like this:

[AMXX] Run time error 3 (plugin "myplugin.amxx") (native "...") - debug not enabled!
[AMXX] To enable debug mode, add "debug" after the plugin name in plugins.ini (without quotes).

Without debug you only know which plugin failed, not where. That is the first thing to fix — you need the line number.

2. Enable debug to get the call trace

Edit addons/amxmodx/configs/plugins.ini and append debug after the failing plugin:

myplugin.amxx debug

Change the map so the plugin reloads, then reproduce the error. Now the log carries a full trace with function names and line numbers:

[AMXX] Displaying debug trace (plugin "myplugin.amxx")
[AMXX] Run time error 3 (stack error)
[AMXX]    [0] myplugin.sma::BuildReport (line 142)

The general workflow for turning cryptic numbers into a line is covered in debugging AMXX plugins. Line 142 is where you look next.

3. Understand why the stack overflows

Pawn gives each plugin one region of memory that the stack grows down into and the heap grows up into. Local variables — anything declared with new inside a function — live on the stack. A big local array eats it fast:

public BuildReport(id)
{
    new huge[8192]   // 8192 cells = 32 KB on the stack, per call
    // ...
}

Declare a couple of those in nested functions, or recurse, and the stack runs into the heap. The VM aborts with error 3. It is a source problem, not a server misconfiguration.

4. Move large buffers off the stack

The correct fix is new static, which allocates the array once in the data segment instead of on the stack every call:

public BuildReport(id)
{
    static huge[8192]   // allocated once, not per call
    // ...
}

Use static for any local array over a few hundred cells and for buffers inside frequently called handlers. If you genuinely need a bigger stack — a menu builder with many moderate buffers, say — you can enlarge the whole region at the top of the .sma:

#pragma dynamic 32768

Raise it and recompile. Treat that as a second resort; converting arrays to static is the real cure and costs nothing at runtime.

5. Watch for recursion and format calls

Two other patterns trigger error 3. Unbounded recursion — a function that calls itself without a hard stop — consumes a stack frame each level until it collides. And formatting into an undersized buffer, then passing it around by value, multiplies stack use. Cap recursion depth explicitly and pass large strings by reference where the API allows it.

6. Catch it before it ships

Error 3 is preventable at compile time if you read the warnings. The compiler reports the estimated stack usage of each function and warns when a local array is large; do not ignore those lines. As a habit, treat any array over roughly 128 cells inside a function as a candidate for static, and keep menu and report builders — the functions that assemble long strings — under review, because they accumulate buffers quickly. A plugin that compiles with a comfortable stack margin will not throw error 3 under a full server, whereas one that compiles right at the edge fails only when several players hit the same handler at once. Fixing it in the source, once, beats chasing intermittent crashes on a live server.

Common errors

  • "debug not enabled!" in every trace — you never added debug in plugins.ini, so you are guessing at the line. Add it and reproduce.
  • Error 3 only under load — a per-player handler with a big local array; 20 players hitting it at once exhausts the stack. Make the array static.
  • Recompiled but it still errors — the old .amxx is still on disk. Confirm the new build deployed and the map changed; see updating plugins live.
  • Different number, same crash — run time error 4 is an array-bounds fault, not a stack fault. That one is covered separately.
  • Only happens on one map — a map-specific config or entity count is pushing an already-marginal plugin over the edge; the stack was too small all along.

Verification

After converting the buffer and recompiling, redeploy, change the map, and drive the exact action that failed — open the menu, run the command, finish the round. Watch the log with the plugin still flagged debug: no new error 3 means the stack no longer collides. Once it is clean for a full map, remove the debug flag so the plugin runs at full JIT speed again. If the trace still points at a huge local, you missed one — grep the source for large new arrays inside functions and make them static.

Katkıda bulunanlar: Daemon666 ✦
Paylaş: