Prodvigat server
57 lines 5.4 KiB Markdown Source Rendered Raw Permalink History
---
title: "Fix: 'error 017: undefined symbol' in Pawn"
excerpt: "Why amxxpc throws error 017 when compiling an AMX Mod X plugin, and the five things that actually cause it: missing includes, wrong-version natives, typos, and scope mistakes."
category: "plugin-dev"
tags: "compiling, errors"
image: ""
read_time: "7 min read"
---
<p><code>error 017: undefined symbol "x"</code> is the single most common failure people hit when compiling AMX Mod X plugins, and it means exactly one thing: the compiler reached an identifier it has no declaration for. Pawn is strongly typed and single-pass over declarations, so every function, native, constant and variable must be visible <em>before</em> the line that uses it. The symbol name in quotes is the whole diagnosis — read it first, then work through the causes below in order.</p>

<h2>1. A missing <code>#include</code></h2>
<p>Natives live in include files, not in the compiler. If you call <code>get_user_flags()</code> without <code>#include &lt;amxmodx&gt;</code>, or a Ham function without <code>#include &lt;hamsandwich&gt;</code>, you get 017 on that exact native. Every plugin needs at least:</p>
<pre>#include &lt;amxmodx&gt;
#include &lt;amxmisc&gt;</pre>
<p>Then add one line per module you touch — <code>&lt;fakemeta&gt;</code>, <code>&lt;hamsandwich&gt;</code>, <code>&lt;cstrike&gt;</code>, <code>&lt;fun&gt;</code>, <code>&lt;sqlx&gt;</code>. Map the undefined symbol to the include that declares it. If you are new to this, <a href="/tutorials/write-first-amxx-plugin">writing your first plugin</a> walks through the standard header block.</p>

<h2>2. The native exists — but not in your AMXX version</h2>
<p>This trap catches experienced coders. <code>client_print_color()</code> was added in <strong>AMX Mod X 1.9</strong>. If your <code>include/</code> folder is from 1.8.2, the compiler has never heard of it and throws 017. The fix is not to hack the include — it is to compile against 1.9 or 1.10 headers and set your plugin's minimum to match. The reverse also happens: you copied a single <code>.inc</code> into a 1.8.2 tree without the natives behind it. Confirm which toolchain you are on before you blame the code; see <a href="/tutorials/compile-sma-to-amxx">compiling .sma to .amxx</a> for pinning the compiler version.</p>

<h2>3. A typo or a case mismatch</h2>
<p>Pawn identifiers are case-sensitive. <code>get_user_Name</code> is a different symbol from <code>get_user_name</code>, and the compiler will not guess. Watch for:</p>
<ul>
<li>Capitalisation: <code>Float:</code> the tag versus <code>float</code>.</li>
<li>Underscores: <code>is_user_alive</code>, not <code>isuseralive</code>.</li>
<li>A constant you meant to <code>#define</code> but spelled differently at the use site.</li>
</ul>

<h2>4. Using a symbol before it is declared</h2>
<p>Pawn reads top to bottom. A <code>#define</code> or a global used above its declaration is undefined at that point:</p>
<pre>public plugin_init() {
    set_task(TASK_TIME, "tick")   // 017: TASK_TIME not yet defined
}
#define TASK_TIME 1.0</pre>
<p>Move constants and globals to the top of the file. Functions are more forgiving — Pawn resolves ordinary function calls in a later pass — but constants and globals must precede their first use.</p>

<h2>5. A public callback that was never written</h2>
<p>When you register a handler by name, the compiler must find a <code>public</code> function with that exact name:</p>
<pre>register_event("DeathMsg", "OnDeath", "a")
// ...
public OnDeath(id) { /* ... */ }   // must exist, spelled identically</pre>
<p>Note that a missing callback more often shows as <code>error 017</code> only if you reference the function elsewhere; a bare string mismatch fails silently at runtime instead. Still, keep the registered string and the <code>public</code> name identical.</p>

<h2>Common errors that look like 017 but are not</h2>
<ul>
<li><strong><code>error 021: symbol already defined</code></strong> — the opposite problem: two globals or two functions share a name. Rename one.</li>
<li><strong><code>warning 213: tag mismatch</code></strong> — usually a <code>Float:</code> passed where a cell is expected. Not fatal, but fix it; it is a real bug most of the time.</li>
<li><strong><code>error 088: number of arguments does not match definition</code></strong> — the native exists and is included, you just called it with the wrong argument count. Check the include for the real signature.</li>
<li><strong>017 on a whole cluster of symbols at once</strong> — almost always a single missing <code>#include</code> near the top, not many separate bugs. Fix the include and recompile before chasing the rest.</li>
</ul>

<h2>Verification</h2>
<p>Recompile and read the summary line. A clean build ends with something like:</p>
<pre>Header size:          1234 bytes
Code size:            5678 bytes
...
0 Errors.</pre>
<p>Only <code>0 Errors.</code> produces a usable <code>.amxx</code>; a build with errors writes nothing. If you compile inside an editor, set it up as in <a href="/tutorials/vscode-amxx-setup">the VS Code AMXX setup</a> so the exact line and symbol jump out. Once it builds, drop the <code>.amxx</code> into <code>addons/amxmodx/plugins/</code>, add it to <code>plugins.ini</code>, and confirm it loads with <code>amxx list</code> in the server console — a plugin that compiled but shows <code>bad load</code> there is a different problem (usually a missing module) covered in <a href="/tutorials/fix-amxx-module-failed-to-load">the module load fix</a>.</p>