Install a script: the walkthrough
Most beginners install a script by dragging the folder in, typing ensure, and hoping. When it works it feels like luck, and when it breaks they have no idea why. This lesson replaces luck with a method. You will install one script the right way, and more importantly you will learn the order of operations that makes every other install predictable. Dependencies first, resource second, database third, load order fourth, console last.
The mental model: install bottom-up
A script almost never stands alone. It calls into other resources, and those resources must already be running and have registered their exports before your script asks for them. So you do not install top-down (the script you want first). You install bottom-up: the things at the base of the stack first, the script that sits on top of them last.
Here is the order, drawn as a stack. Read it from the bottom.
┌─────────────────────────────┐
install LAST │ qs_lockpick │ the script you actually want
│ needs: oxmysql, ox_lib, │
│ a framework │
├─────────────────────────────┤
│ es_extended / qb-core │ framework (player data, jobs)
│ needs: oxmysql, ox_lib │
├─────────────────────────────┤
│ ox_lib │ shared library (UI, callbacks)
├─────────────────────────────┤
install FIRST │ oxmysql │ database layer -> MariaDB
└─────────────────────────────┘
loads top-down in server.cfg,
so write deps ABOVE the scriptIn server.cfg the load order is literally the top-to-bottom order of your ensure lines. So the resource that everyone depends on, oxmysql, gets ensured first, and your script gets ensured last. If you flip that, your script boots before oxmysql exists and you get attempt to call a nil value the instant it starts. That one rule prevents most install failures.
Note the names. oxmysql, ox_lib, ox_target, and ox_inventory are Overextended community resources, not official Cfx.re resources. Your database engine is MariaDB (the modern drop-in for MySQL). On the framework line, Qbox (qbx_core) is the actively maintained QBCore successor, while classic QBCore development has stalled. ESX (es_extended) is also current. Pick whichever your script's README names.
Build it
Read the README and the fxmanifest
Before you touch a single folder, open the script's README.md and its fxmanifest.lua. You are hunting for three things: its dependencies, whether it ships a .sql file, and which framework it targets.
The README usually states it in plain English near the top. The fxmanifest.lua states it in machine-readable form with the dependencies key:
fx_version 'cerulean'
game 'gta5'
author 'SomeDev'
description 'Lockpick minigame'
version '1.0.0'
shared_script '@ox_lib/init.lua' -- the @ prefix means: load from another resource
client_script 'client.lua'
server_script {
'@oxmysql/lib/MySQL.lua', -- pulls oxmysql's query API into this script
'server.lua'
}
How it works
You installed it in a specific order and it booted clean. Now take the order apart, because the why behind each step is what lets you install any script, not just this one.
Why dependencies go in first
A resource registers its exports and events only once it has started. oxmysql registers its query API when it boots; ox_lib registers lib.* when it boots; your framework registers the player object when it boots. Your script calls all of those the moment it starts. If the thing it calls has not started yet, the call resolves to nil, and Lua throws attempt to call a nil value.
So the rule is not a style preference. It is cause and effect. The dependency must be running before the dependent asks it for anything. Installing bottom-up, and ordering server.cfg top-down with deps above the script, is how you guarantee that.
Why the .sql import is its own step
A script's code and a script's database are two separate things you must both provide. The folder you dropped in is the code. The .sql file is the shape of the data the code expects: tables, columns, keys. FiveM starts the code regardless of whether the tables exist, because it has no idea what your script will query. The mismatch only surfaces at runtime, the first time the code runs a SELECT or INSERT against a table that was never created.
That is why no such table is a database error, not a code error. The connection worked. The script ran. The table simply was never imported. Importing the .sql before the first run closes that gap. If a script ships no .sql file, it stores nothing in the database and you skip this step entirely, which is itself useful information about what the script does.
Why load order is the order of the lines
There is no separate "priority" setting in server.cfg. The order resources start in is exactly the order their ensure lines appear, read top to bottom. Bracketed [category] folders like [framework] and [scripts] only group resources for tidiness; they do not control fine-grained order. So two scripts where one depends on the other must still be ordered by hand in server.cfg, dependency first.
Your script errors with 'attempt to call a nil value' on the oxmysql export the instant it starts, even though oxmysql is installed and working. What is almost certainly wrong?
The load order in server.cfg is backwards: your script is ensured above ensure oxmysql, so it starts before oxmysql has registered its exports. At that moment exports.oxmysql is still nil, the call fails, and you get attempt to call a nil value. The fix is not in the code. Move the ensure oxmysql line above the ensure qs_lockpick line, restart, and the export exists by the time your script asks for it. This is why the install order and the server.cfg order have to match the dependency stack.
The repeatable checklist
Strip away the specific names and you have a checklist that works for every script you will ever install:
- Read. Open the README and the
fxmanifest.lua. List thedependencies, note every@resource/...path, find any.sqlfile, and identify the target framework. - Dependencies first. Install
oxmysql,ox_lib, the framework, and anything else on the list, intoresources, with their real folder names. - Drop the resource. Put the script in
resources/[scripts], withfxmanifest.luaat the top level of its folder. - Import the SQL. If it ships a
.sql, run it into your MariaDB database with HeidiSQL, then confirm the tables exist. - Order it. Add
ensurelines inserver.cfgwith every dependency above the script. - Restart and read. Run
refreshthenensure <script>, and read the console for its start banner and for red.
Six steps, same order, every time. When step six shows red instead of a clean banner, that is your cue to switch from installing to diagnosing.
Common mistakes
| Symptom | Fix |
|---|---|
attempt to call a nil value (the script's first oxmysql or framework call) | Load order is wrong. The script is ensured before its dependency in server.cfg. Move ensure oxmysql / ensure ox_lib / the framework ABOVE the script's ensure line, then restart. |
no such table 'lockpick_attempts' | The connection works but the .sql was never imported, or it ran against the wrong database. In HeidiSQL select your fivem database first, run the script's .sql file, then SHOW TABLES to confirm. |
Could not find resource qs_lockpick / it does not show in the resource list | Either the folder is nested (qs_lockpick/qs_lockpick/fxmanifest.lua) so the manifest is one level too deep, or you added it live and never ran refresh. Flatten the folder so fxmanifest.lua is at the top, then run refresh and ensure again. |
Unable to establish a connection to the database | This is oxmysql, not your script. The mysql_connection_string is missing or wrong, or MariaDB is not running. Fix the convar (mysql://user:pass@localhost:3306/db) and confirm the database engine is started before retrying. |
Failed to load resource qs_lockpick: it depends on ox_lib, which couldn't be started | A named dependency is missing or failed. Confirm ox_lib (and every name in the dependencies block) is actually in resources with that exact folder name and is ensured earlier in server.cfg. |
Could not load resource because it was already declared | The same folder name exists twice in the resources tree (a stray copy in another category folder). FiveM keys resources by folder name, not path. Delete the duplicate. |
What you can do now
- Read a script's README and fxmanifest to list its dependencies, spot @resource paths, and find any .sql file.
- Install dependencies bottom-up: oxmysql, then ox_lib, then the framework, before the script itself.
- Drop a resource into resources/[scripts] with its fxmanifest.lua at the top level of the folder.
- Import a script's .sql into MariaDB with HeidiSQL and confirm the tables exist before the first run.
- Order ensure lines in server.cfg so every dependency starts above the script, then refresh, ensure, and read the console for the start banner.