Romania XPlayZM.CSBlackDevil.COM # Zombie Plague UltimateX [ Respawn + FDL + VIP 22-12PM + POINTS] ® 28/32
Unknown ❤ RESPAWN.ZAFEST.RO | VIP FREE | FREE FOR ALL ❤ 0/32
France EMIRATES.KiNGS 亗 GAMEAREA ||͇̿P͇̿U͇̿B͇̿L͇̿I͇̿C͇̿| ✪ 32/32
Sunucu tanitimi
65 lines 5.6 KiB Markdown Source Rendered Raw Permalink History
---
title: "Debugging AMXX Plugins: debug Mode, server_print and Logs"
excerpt: "Turn on plugin debug mode for line numbers in run-time errors, use server_print and log_amx to trace state, and read the AMXX logs to find the real fault."
category: "plugin-dev"
tags: "debugging, amxmodx"
image: ""
read_time: "7 min read"
---
<p>When an AMXX plugin misbehaves you have three tools, and used together they resolve almost everything: debug mode (so run-time errors carry line numbers), print/log natives (so you can trace state), and the AMXX log files (where the engine already wrote down what went wrong). The mistake most people make is guessing before reading the log. This guide is the order to work in.</p>

<h2>1. Read the log first</h2>
<p>AMX Mod X writes to dated files under <code>cstrike/addons/amxmodx/logs/</code>. Before changing any code, open the newest one. A run-time error is already recorded there with the plugin name and, if debug mode is on, the exact line:</p>
<pre>L 07/15/2026 - 21:14:03: [AMXX] Run time error 4 (index out of bounds)
L 07/15/2026 - 21:14:03: [AMXX]    [0] myplugin.sma::give_award (line 88)</pre>
<p>That second line &mdash; the call trace with a line number &mdash; only appears when the plugin runs in debug mode. Without it you get the error but not the location, which is why step 2 exists.</p>

<h2>2. Turn on debug mode</h2>
<p>Debug mode is per-plugin and set in <code>plugins.ini</code>. Add the word <code>debug</code> after the plugin filename:</p>
<pre>; cstrike/addons/amxmodx/configs/plugins.ini
myplugin.amxx debug</pre>
<p>Change the map or restart, reproduce the error, and the log now shows the file, function, and line. Debug mode adds overhead, so use it while investigating and remove it on a busy production server once fixed. Plugins compiled locally already carry debug symbols; the <code>debug</code> keyword is what tells AMXX to <em>use</em> them at runtime.</p>

<h2>3. Trace state with server_print and log_amx</h2>
<p><code>server_print</code> writes to the server console immediately &mdash; ideal for watching values as they change while you have a console open. <code>log_amx</code> writes to the AMXX log with a timestamp, which survives after the moment passes:</p>
<pre>public give_award(id)
{
    server_print("give_award: id=%d alive=%d frags=%d",
        id, is_user_alive(id), get_user_frags(id))

    if (!is_user_connected(id))
    {
        log_amx("give_award called with invalid id %d", id)
        return
    }
    // ...
}</pre>
<p>Use <code>server_print</code> for live tracing and <code>log_amx</code> (or <code>log_to_file</code> for a dedicated file) for anything you need to inspect after the fact &mdash; an intermittent bug that happens once an hour is not something you will catch staring at the console.</p>

<h2>4. Bail out cleanly with set_fail_state</h2>
<p>If a plugin cannot run &mdash; a required cvar is missing, a module did not load, a table is absent &mdash; do not limp on and crash later. <code>set_fail_state</code> stops the plugin with a logged reason:</p>
<pre>public plugin_init()
{
    register_plugin("Award", "1.0", "CSB")

    if (!cvar_exists("mp_startmoney"))
        set_fail_state("required cvar mp_startmoney missing")
}</pre>
<p>A plugin in the failed state shows as <code>debug</code>/<code>bad load</code> in <code>amxx plugins</code>, with your message in the log &mdash; far easier to diagnose than a null-index crash three functions later.</p>

<h2>5. Inspect loaded plugins live</h2>
<p>From the server console, <code>amxx plugins</code> lists every plugin and its status: <code>running</code>, <code>paused</code>, <code>debug</code>, or <code>bad load</code>. <code>amxx modules</code> does the same for modules. A plugin that depends on <code>fakemeta</code> or <code>reapi</code> showing <code>bad load</code> almost always means the module underneath it failed &mdash; check <code>amxx modules</code> before blaming the plugin:</p>
<pre>amxx plugins
amxx modules</pre>

<h2>Common errors and what they mean</h2>
<ul>
<li><strong><code>Run time error 4 (index out of bounds)</code></strong> &mdash; an array or player index out of range, very often an id of 0 (the world) or 33+. Guard with <code>is_user_connected</code>. Full walkthrough: <a href="/tutorials/fix-amxx-run-time-error-4">run-time error 4</a>.</li>
<li><strong><code>Run time error 10 (native error)</code></strong> &mdash; a native was called with a bad argument, e.g. an invalid entity. The trace line points at the call.</li>
<li><strong>No line numbers in the trace</strong> &mdash; debug mode is off. Add <code>debug</code> in <code>plugins.ini</code> and reproduce.</li>
<li><strong>Plugin shows <code>bad load</code></strong> &mdash; a missing module or a plugin compiled against a newer AMXX. See <a href="/tutorials/fix-amxx-module-failed-to-load">module failed to load</a> and <a href="/tutorials/fix-plugins-bad-load-after-19">bad load after upgrading</a>.</li>
<li><strong>Console flooded, server lags</strong> &mdash; you left a <code>server_print</code> inside a per-frame hook like <code>FM_PlayerPreThink</code>. Remove trace prints from hot paths before shipping.</li>
</ul>

<h2>Verification</h2>
<p>Reproduce the bug with debug mode on and confirm the log now names the exact line. Fix it, reload, and confirm the error is gone from a fresh log file &mdash; not just absent from the console, which can lie if the plugin failed to reload. When a whole plugin refuses to start, <code>amxx plugins</code> plus the newest log file will tell you whether it is the plugin or a module beneath it. To narrow down which of many plugins is crashing the server, see <a href="/tutorials/find-crashing-plugin">finding the crashing plugin</a>.</p>