FiveM Server Won't Start? Boot-Failure Triage: Artifact Rollbacks and Resource Bisection

FiveM Server Won't Start? Boot-Failure Triage: Artifact Rollbacks and Resource Bisection

A dead FXServer at peak hours is a solvable problem, but only if you work it like an incident instead of guessing. When your fivem server won't start, the gap between a five-minute fix and a ruined evening is almost always where you look first — not how many things you change at once. This runbook walks the triage in the order a seasoned operator actually runs it: find the true error, clear the handful of boot killers behind most of these, roll back a bad artifact, and — when nothing is obvious — bisect your resources properly instead of flailing through reboots.

Read the first error, not the last

When FXServer fails to boot, scroll up to the first error in the console, not the last one on screen. The earliest failure is usually the cause; everything below it is a cascade of resources choking on the broken state it left behind. Fix the first red line, restart, and re-read from the top.

That first error hides in one of three places:

A SCRIPT ERROR at the bottom naming esx_something is frequently a victim, not the culprit. oxmysql or es_extended failed 300 lines earlier, and every dependent resource is now erroring on a nil. Chase the origin, not the noise.

The boot killers behind most failures

Four causes account for the overwhelming majority of "it just won't boot" tickets. Match the console text to the likely cause, then run the first move.

| Console says | Likely cause | First move |
|---|---|---|
| Could not bind on 0.0.0.0:30120 | Zombie FXServer holding the port | Kill the old PID |
| Silent stop after a server.cfg line | Unbalanced quote or bad exec | Diff your last cfg edit |
| Failed to load resource ...: manifest | fxmanifest.lua syntax | Validate the manifest |
| ECONNREFUSED / oxmysql connection | MySQL down or wrong creds | Check the DB service |

A server.cfg edit you just made

Most boot failures land right after someone touched server.cfg. The classic three: an unbalanced quote — one stray " makes the parser swallow every following line, so the real error looks nothing like the mistake — a duplicate ensure for a resource already pulled in by a [category] bracket, and an exec pointing at a file that no longer exists. If it worked an hour ago, git diff or your editor's undo history beats reading the console. Locking down who can even touch the live config prevents half of these; that's the case for tight FiveM server access control.

A resource manifest that won't parse

fxmanifest.lua is Lua, and Lua is unforgiving about a missing comma inside a client_scripts { ... } table or a stray end. A wrong fx_version (current builds want 'cerulean') or a missing game 'gta5' refuses the load outright.

fx_version 'cerulean'
game 'gta5'

shared_scripts { '@ox_lib/init.lua' 'config.lua' }   -- missing comma = boot fail
client_scripts { 'client/*.lua' }
server_scripts { '@oxmysql/lib/MySQL.lua', 'server/*.lua' }

The console names the offending resource but rarely the line. When in doubt, revert the manifest to the last-known-good copy and re-add your change one field at a time. For deeper manifest and config-syntax breakdowns, cfx-tebex.store's resource guides go field by field.

The database is unreachable

oxmysql throwing ECONNREFUSED at boot means the connection was refused, not misconfigured — MySQL isn't listening where you pointed it. Check the service before you touch the string:

systemctl status mariadb      # or: systemctl status mysql
ss -tlnp | grep 3306          # is anything listening on the DB port?

Then sanity-check the convar — host, port, user, password, database:

set mysql_connection_string "mysql://fivem:[email protected]:3306/es_extended?charset=utf8mb4"

localhost and 127.0.0.1 are not always interchangeable: localhost can resolve to a unix socket your MySQL isn't bound to, while 127.0.0.1 forces TCP. If the service is up and the creds are right but the connection still refuses, pin the numeric host.

The port is already bound

Could not bind on 0.0.0.0:30120 means a previous FXServer never fully died and still owns the port. Find it and kill it:

ss -tulpn | grep 30120        # find the PID holding the port
# or: lsof -i :30120
kill 12345                    # graceful first; kill -9 only if it won't go

On Windows: netstat -ano | findstr :30120, then taskkill /F /PID 12345. Orphaned txAdmin child processes are the usual offenders after a crash-restart loop leaves one dangling.

When the last change was an artifact update

If it booted yesterday and the only thing that changed is the FXServer build, treat the artifact as the prime suspect and roll it back. This is the emergency version — you are down now, not planning a deploy.

# artifacts kept per build; your launcher points at one of them
ls ~/fxserver/artifacts/          # 12180  12345  12420
# roll back: repoint the run script / systemd unit at the known-good build
sed -i 's#artifacts/12420#artifacts/12180#' ~/fxserver/run-server.sh
systemctl restart fivem

Two habits turn this into a non-event. Keep the last three or four artifact folders on disk instead of overwriting in place, so a rollback is a path swap and a restart. And record the build number in your changelog every time you bump, so "known-good" is a fact you can look up, not a guess. One trap on the way back: Cfx.re periodically raises the minimum supported build, so rolling too far back can bounce clients with a version error. Roll back one or two releases, not one from last spring.

Clear the server cache — safely

A corrupted cache/ folder in your server-data directory can wedge a boot after a bad update or an interrupted download. It regenerates on its own, so deleting it is safe while the server is stopped:

# stopped server only
rm -rf ~/fxserver/server-data/cache/

What you never delete in a panic: resources/, server.cfg, or anything under your database. Those aren't cache — those are the server. Stop, clear cache/, start, and let FXServer rebuild it.

When nothing is obvious: bisect your resources

No clear error and a folder holding a hundred resources is where people burn an afternoon. Don't disable them one at a time — that's up to a hundred reboots. Binary-search it: disable half, boot, and let the result point at the guilty half.

Two things quietly sabotage a naive bisection.

Alphabetical load order lies. Resources don't load alphabetically or by folder — they load in the order of your ensure/start lines and [bracket] auto-ensures in server.cfg. "Disable half the folder" is meaningless; disable half the cfg load list. And a crash pinned on zzz_last can be set up by aaa_first corrupting shared state on the way up, so trust the boot order, not the filename.

Dependency chains break the cut. You cannot bisect away your framework. If the half you disable contains oxmysql, ox_lib, or es_extended/qb-core, every resource that depends on them errors out and every round hands you a false positive. Pin the core stack ON in every round and bisect only the leaf resources:

## always-on during a bisect
ensure oxmysql
ensure ox_lib
ensure es_extended

## bisect these — comment out half, reboot, repeat
ensure resource_a
ensure resource_b
# ensure resource_c
# ensure resource_d

Re-read the first error each round. Disabling half sometimes changes which resource fails first and hands you the answer for free.

Keep a safe-mode server.cfg committed

The fastest bisection starts from a known-good floor. Keep a server.safe.cfg in version control that boots only the framework, a spawn manager, and chat — nothing else. When a boot dies mysteriously, exec that instead:

./run.sh +exec server.safe.cfg

If safe-mode boots, the fault is one of the resources you left out, and you bisect up from a clean base instead of down from chaos. If even safe-mode won't start, the problem is the artifact, the database, or the port — and you've ruled out ninety-odd resources in a single boot. Commit the safe config next to your real one so it's always current, never a stale copy from three migrations ago.

txAdmin recovery, and isolating the layer

txAdmin runs FXServer as a child process, which adds a layer that can itself be the thing that's broken. If the txAdmin live console shows a clean boot error, fix that error. If txAdmin itself won't come up, bypass it: run FXServer straight from the command line with +exec server.cfg. Booting clean without txAdmin tells you the fault lives in txAdmin's config under txData/, not in your server — and you can reset that profile without touching a single resource. txAdmin's own restart-on-crash can also mask the real error by looping too fast to read; stop the loop, run once by hand, and read the first error in peace.

Write the postmortem so 3am-you doesn't solve it twice

Every boot failure you fix is worth two minutes of notes: what the first error said, what actually caused it, and the exact command that fixed it. Keep it in the same repo as your server.cfg. Six weeks later, when the same missing-comma-after-an-update failure hits during a live event, past-you has already written the answer — and 3am-you gets to go back to bed instead of rediscovering it under pressure.

Get the server breathing first; chase the numbers after. Once it's back up and joinable, that's the moment to profile what's heavy with a FiveM performance pass, and to keep the resources themselves clean with well-built FiveM scripts that don't fight your boot in the first place.

Related posts

Guide
FiveM Resource Deployment Done Right: Git, Staging and Updating a Live Server Without Downtime
Guide
FiveM Server Monitoring: Uptime Alerts, Resource Graphs and Catching Crashes Before Players Notice
Guide
Linux for FiveM Server Owners: systemd, File Permissions and the Commands That Keep Your City Up
Published · Jul 09, 2026 Read more posts →