FiveM Drug Scripts Troubleshooting FAQ: 12 Common Issues Fixed
Drug scripts combine inventory systems, processing loops, NPC interactions, police dispatch, and economy integration — more moving parts means more failure points. This guide covers the 12 most common failures across ESX, QBCore, and QBox with diagnostic steps and working code.

Drug scripts are among the most complex resources on any FiveM server. Processing loops, grow house timers, NPC dealers, police dispatch integration, cooldown systems, skill trees — every layer can fail independently, and failures often look identical from the player's perspective: nothing happens.
This guide covers the 12 most common drug script failures across ESX, QBCore, and QBox. Each section identifies the actual root cause rather than generic advice, and includes working code to verify and fix it.
Quick Diagnosis Table

Match the symptom to the most likely cause before diving into individual sections.
| Symptom | Most likely cause | First thing to check |
|---|---|---|
| Processing won't start | Item not in shared items or zone wrong | Print item name, teleport to zone coords |
| Sell earnings disappear on restart | Money add without DB persist | Server console for SQL errors on sell |
| Sell location has no NPC | Ped model invalid or coords inside geometry | Test with a_m_y_business_01 at same coords |
| No interaction prompt at seller | Zone radius too small or deleted | Check zone radius in config |
| Plants reset on restart | Grow state in memory only | Query grow_houses table after planting |
| Drug effects don't fire | Event not reaching client or loop clearing effects | Add debug print in consumption event |
| Crafting fails silently | Item name mismatch | Copy name directly from shared items file |
| No police dispatch alert | Dispatch resource down or wrong export | Verify ensure order + export name |
| Weight conflict at pickup | Weight defined twice | Remove local weight, use shared items only |
| Dealer NPC missing | Model not streamed or bad coordinates | Test with default ped model |
| Route breaks at waypoint | Distance threshold too tight | Print checkpoint index on arrival |
| XP not saving | DB write failing or row never inserted | Query drug_skills table directly |
| Lab prop not interactable | Zone coords don't match prop position | Print prop coords vs zone config |
1. Drug Processing Not Starting
Processing is the core gameplay loop. When it fails, players can't transform raw materials into sellable product.
First, confirm every item in the processing chain is registered in your framework's shared items:
QBCore — check qb-core/shared/items.lua:
['weed_raw'] = {
['name'] = 'weed_raw',
['label'] = 'Raw Weed',
['weight'] = 100,
['type'] = 'item',
['image'] = 'weed_raw.png',
['unique'] = false,
['useable'] = false,
['shouldClose'] = false,
['combinable'] = nil,
['description'] = 'Fresh cannabis plant material'
},
['weed_processed'] = {
['name'] = 'weed_processed',
['label'] = 'Processed Weed',
['weight'] = 50,
['type'] = 'item',
['image'] = 'weed_processed.png',
},
A missing item entry produces no error — the processing event fires, finds no item, and exits silently.
Next, teleport to the processing zone coordinates from your config and confirm the zone is accessible:
-- Debug: print processing zone coordinates from F8
print(json.encode(Config.ProcessingZones[1]))
-- Then use /tp in-game or vMenu to teleport to those coords
Fix checklist:
- All drug items (raw, processed, packaged) exist in shared items
- Processing zone coordinates are on valid ground (not inside walls)
- Required inventory resource (ox_inventory, qb-inventory) is running and started before the drug resource
- No F8 errors when entering the zone — zone registration failures show immediately
Framework note: On QBCore with ox_inventory, item usability is set separately from item registration. A useable = false item can exist in inventory but never trigger the use event. Set useable = true and register the server-side use handler.
2. Drug Money Not Saving
If players earn money from selling drugs but the balance resets on server restart, the sell event is adding money without persisting the change to the database.
ESX — money add without persist (broken):
xPlayer.addMoney(amount) -- adds to memory only
ESX — money add with persist (correct):
xPlayer.addMoney(amount)
MySQL.update('UPDATE users SET money = ? WHERE identifier = ?',
{xPlayer.getMoney(), xPlayer.identifier})
QBCore — addMoney persists automatically:
-- QBCore's AddMoney writes to the players table
Player.Functions.AddMoney('cash', amount, 'drug-sale')
To verify persistence, add a print after the DB write and check the server console during a test sell:
print('[drug-sell] Wrote $' .. amount .. ' to DB for ' .. identifier)
If the print fires but the database doesn't update, the MySQL query is failing silently. Enable query error logging in your database resource (oxmysql logs errors by default; mysql-async requires Config.Debug = true).
3. Selling Locations Broken
Broken sell locations manifest in one of three ways: no NPC visible, no interaction prompt, or the sell event fires but the transaction fails.
Test the NPC spawn independently to isolate the cause:
-- Client-side test: spawn a dealer at the sell location coords
local model = GetHashKey('a_m_y_business_01')
RequestModel(model)
while not HasModelLoaded(model) do Wait(10) end
local coords = Config.SellLocations[1].coords
local ped = CreatePed(4, model, coords.x, coords.y, coords.z, coords.w or 0.0, false, false)
SetBlockingOfNonTemporaryEvents(ped, true)
FreezeEntityPosition(ped, true)
If this test ped spawns, your original ped model name is invalid — find the correct spawn name in the GTA V vehicle/ped database or use /modelpreview if you have vMenu installed.
If the NPC is present but shows no prompt, the interaction zone is missing or has a radius too small. Most ox_target and qb-target zones need a radius of at least 1.5 units around the ped's position.
ESX-specific: On ESX, drug sell locations often use ESX.Game.SpawnPed which wraps CreatePed with a streaming check. If the model never loads, the function silently exits. Add a timeout:
ESX.Game.SpawnPed(model, coords, heading, function(ped)
if not ped then
print('[drug-sell] Ped failed to spawn at ' .. json.encode(coords))
return
end
-- zone creation here
end)
4. Grow Houses Not Working
Grow houses require state that survives server restarts. Each plant needs a database row tracking its stage, water level, and the Unix timestamp of the last growth tick.
Verify the table exists and contains data after planting:
-- Check table structure
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'grow_houses';
-- Check if plants were written
SELECT * FROM grow_houses ORDER BY planted_at DESC LIMIT 10;
If rows exist but growth resets, the initialization code reads plants from memory (which starts empty on restart) instead of from the database. Look for code like this in the server-side init:
-- Wrong: starts fresh every restart
local plants = {}
-- Correct: loads existing plant state from DB
local plants = MySQL.query.await('SELECT * FROM grow_houses WHERE harvested = 0')
QBCore grow script note: Many community grow scripts store growth stage as an integer and advance it on a timer. If the timer interval is Config.GrowTime * 60 * 1000 but Config.GrowTime is nil (missing from config), the timer fires every 0ms and locks the server thread. Add a nil check:
local growInterval = (Config.GrowTime or 60) * 60 * 1000
5. Drug Effects Not Applying
Visual and physical drug effects run entirely client-side using GTA screen effect natives. If consuming a drug does nothing:
Add a print at the top of the consumption event handler:
RegisterNetEvent('drug:client:consumeItem')
AddEventHandler('drug:client:consumeItem', function(drugType, amount)
print('[DEBUG] Drug effect triggered: ' .. tostring(drugType))
-- Effect code runs after this
end)
If the print doesn't appear, the server isn't triggering the client event. Check that the server-side consume handler calls TriggerClientEvent with the correct event name and the player's source.
If the print fires but no effect shows, another resource is resetting screen effects. Test by disabling HUD scripts, status systems (hunger/thirst), and weather sync resources one at a time:
-- Test effect directly in F8
AnimpostfxPlay('DrugsMichaelAliensFight', 0, true)
SetTimecycleModifier('drug_flying_base')
If these fire correctly in isolation, a competing resource is the culprit. Search all resources for ClearTimecycleModifier or AnimpostfxStopAll calls on a loop.
6. Crafting Table Errors
Drug crafting requires exact item name alignment between three places: the crafting recipe config, the inventory's item registration, and the player's actual inventory items.
The single most effective fix: copy-paste item names directly from your shared items file instead of typing them. One incorrect character — a capital letter, an underscore vs hyphen, a space — breaks the match silently.
Verify all recipe items exist:
QBCore — quick check for missing items:
-- Server-side: verify recipe items exist at resource start
for _, recipe in pairs(Config.Crafting) do
for _, ingredient in pairs(recipe.ingredients) do
if not QBCore.Shared.Items[ingredient.item] then
print('[DRUG-CRAFT ERROR] Missing item: ' .. ingredient.item)
end
end
if not QBCore.Shared.Items[recipe.output] then
print('[DRUG-CRAFT ERROR] Missing output item: ' .. recipe.output)
end
end
Add this check to your drug resource's server startup. It surfaces every bad item name before a player ever attempts to craft.
ox_inventory note: ox_inventory uses a separate item registration format from QBCore shared items. If you're using ox_inventory, items must be defined in ox_inventory/data/items.lua, not just in qb-core/shared/items.lua.
7. Police Alerts Not Triggering
Drug scripts call a dispatch resource when players perform illegal activities. The export name varies by installed dispatch resource.
Check which dispatch resource you have running:
# In server console
resmon
# Look for cd_dispatch, ps-dispatch, qs-dispatch, or linden_outlawalert
Then verify the export call in your drug script matches:
-- cd_dispatch (most common on ESX)
exports['cd_dispatch']:AlertMessage({
message = 'Drug Activity',
blipSprite = 306,
coords = GetEntityCoords(PlayerPedId()),
length = 7500
})
-- ps-dispatch (common on QBCore)
exports['ps-dispatch']:DrugActivity()
-- qs-dispatch
exports['qs-dispatch']:SendAlert({type = 'drug'})
If the export name is correct but no alert fires, verify the dispatch resource starts before the drug resource in server.cfg. An export called before the providing resource starts returns nil.
ESX vs QBCore difference: ESX servers typically run cd_dispatch; QBCore servers typically run ps-dispatch or qs-dispatch. A drug script written for ESX will call the wrong export on a QBCore server — update the export name in the drug script's dispatch config.
8. Weight System Conflicts
When drug items display incorrect weight or the inventory rejects pickup with "too heavy," the item weight is defined in multiple places with conflicting values.
The rule: define weight once, in your framework's shared items file, and nowhere else.
-- QBCore shared items: the authoritative weight
['cocaine'] = {
['name'] = 'cocaine',
['label'] = 'Cocaine',
['weight'] = 50, -- THIS is the weight
['type'] = 'item',
},
-- Drug script config: should NOT override weight
Config.Items = {
['cocaine'] = {
label = 'Cocaine',
-- No weight field here
}
}
If the drug script has a local weight field in its item config, remove it. If the inventory system uses its own item registration (ox_inventory), update the weight there and remove the shared items entry.
After changing weights, restart both the inventory resource and the drug resource. In-game items already held by players retain their old weight until the player drops and picks them up again.
9. NPC Drug Dealer Not Spawning
Dealer NPC failures come from three sources, in order of likelihood:
Invalid ped model: The model name is misspelled or the model needs streaming. Test with a_m_y_business_01:
-- Test in F8
local model = GetHashKey('a_m_y_business_01')
RequestModel(model)
local timeout = GetGameTimer() + 5000
while not HasModelLoaded(model) and GetGameTimer() < timeout do Wait(10) end
if HasModelLoaded(model) then
print('Model loaded successfully')
CreatePed(4, model, -200.0, -300.0, 40.0, 90.0, false, false)
end
Bad coordinates: The spawn point is inside a wall, underground, or in an unloaded interior. Add 1.0 to the Z coordinate and test. For MLO interiors, you must call LoadInterior before spawning peds inside.
Resource load order: The drug resource starts before the framework fully initializes. Move the drug resource's ensure line below the framework and all dependency resources in server.cfg.
10. Custom Drug Routes Not Working
Route-based drug missions chain multiple waypoints. When the route breaks at a specific point, the player arrives but the script doesn't advance.
Add a print inside the checkpoint handler to identify exactly which index fails:
RegisterNetEvent('drug:client:checkpointReached')
AddEventHandler('drug:client:checkpointReached', function(index)
print('[DEBUG] Reached checkpoint ' .. tostring(index))
-- advancement logic
end)
Common failure causes, in order:
-
Distance threshold too tight: A check under 2.0 units requires the player to walk to within 2 meters of an exact coordinate. On uneven terrain, this often fails. Increase to 5.0 for outdoor waypoints.
-
Nil coordinates: A missing entry in the route config silently produces
(0, 0, 0)as the target waypoint, which is underground in the ocean. Add nil checks:
for i, waypoint in ipairs(Config.Routes[routeId].waypoints) do
if not waypoint or not waypoint.x then
print('[drug-route ERROR] Nil waypoint at index ' .. i)
end
end
- Client-server sync: The checkpoint event fires on the client but the server doesn't receive it. Verify
TriggerServerEventis called, not a local function.
11. Skill Tree Not Progressing
Drug skill trees track XP in the database and unlock bonuses as players grind. If XP never accumulates:
Query the player's skill record directly:
SELECT * FROM drug_skills WHERE identifier = 'char1:abc123';
If the row is missing, the initial insert never ran — usually because the player joined before the drug resource fully started, or the INSERT silently failed. Create the row manually and test:
INSERT INTO drug_skills (identifier, xp, level)
VALUES ('char1:abc123', 0, 1);
If the row exists but XP doesn't increase after actions, the XP write event isn't triggering on the server side. Add a print inside the server-side XP handler:
RegisterNetEvent('drug:server:addXP')
AddEventHandler('drug:server:addXP', function(amount)
local src = source
local identifier = GetPlayerIdentifier(src, 0)
print('[DEBUG] XP event received: ' .. tostring(amount) .. ' for ' .. identifier)
-- DB write here
end)
Framework note: Some drug scripts use exports['oxmysql']:executeSync for XP writes. If oxmysql isn't installed (the server uses mysql-async instead), this silently errors and XP never saves. Match the MySQL resource to what the script expects.
12. Lab Equipment Not Interactable
Lab equipment — chemistry tables, processing stations, packaging machines — uses ox_target or qb-target zones attached to prop coordinates. When the zone exists but the player can't interact:
Print the prop's current world position and compare it to the zone's registered coordinates:
-- Client-side: find the prop and print its position
local props = GetGamePool('CObject')
for _, obj in ipairs(props) do
local model = GetEntityModel(obj)
if model == GetHashKey('ch_prop_ch_drugtable_01a') then
local pos = GetEntityCoords(obj)
print(string.format('Prop at: %.2f, %.2f, %.2f', pos.x, pos.y, pos.z))
end
end
If the prop's position differs from the zone config by more than 0.5 units, update the zone coordinates. This drift happens when:
- The MLO containing the lab was updated and props moved
- A different MLO variant is loaded (some have two variants with different layouts)
- Another script moves or recreates the prop
Also verify the interaction event name after a script update — event names change between major versions and the zone will register successfully even if the target event no longer exists.
Related Guides
- FiveM Police Scripts Troubleshooting FAQ — Dispatch, MDT, and cop-side integration issues
- FiveM Economy Scripts Troubleshooting FAQ — Money persistence, society funds, and inflation
- FiveM HUD Scripts Troubleshooting FAQ — When HUD scripts interfere with drug effect timecycles
Recommended Scripts
Looking for reliable, tested drug scripts for your server?
- FiveM Drug Scripts — Premium and free drug systems
- QBCore Drug Scripts — QBCore-specific drug resources
- Best FiveM Scripts 2026 — Top-rated scripts across all categories
Frequently Asked Questions
Why is my FiveM drug processing not starting?
Drug processing fails when the input item isn't registered in your framework's shared items list, the processing zone coordinates are wrong, or a required dependency (ox_inventory, qb-inventory) isn't running. Print the item name from the inventory trigger and compare it letter-for-letter against the shared items key. Teleport to the processing zone coordinates to verify they're accessible. Check F8 for zone registration errors from qb-target or ox_target.
Why isn't drug money saving after a server restart?
If drug earnings disappear on restart, the sell event is writing money to the player's in-memory balance without triggering a database persist. The fix depends on your framework: on ESX, call xPlayer.addMoney followed by a MySQL.update; on QBCore, use Player.Functions.AddMoney which writes to the players table automatically. Check the server console for SQL errors after a sell event — a silently failing INSERT is the most common cause.
Why are selling locations broken in my drug script?
Broken sell locations typically mean the NPC isn't spawning, the interaction zone isn't registering, or the sell event fires but the NPC refuses the transaction. Test the NPC spawn independently with a common ped model at the same coordinates. If the NPC appears but gives no interaction prompt, the zone radius is too small or another script deleted it. If the zone works but selling fails, the sell event is throwing a server-side error — check the server console.
Why aren't grow houses working in my FiveM server?
Grow houses need persistent state: plant stage, water level, and growth timestamps must survive server restarts. If plants reset on every restart, the script is storing grow state in memory instead of the database. Verify the grow_houses table exists in your database and contains rows after planting. If rows exist but stages reset, the growth tick event reads from memory instead of the DB on server start — check the resource's initialization code.
Why are drug effects not applying to players?
Drug consumption effects use client-side GTA natives like SetTimecycleModifier and SetPedMotionBlur. If they don't fire, add a print inside the client-side consumption event to confirm the event is received. If the print fires but no visual effect appears, another script is clearing screen effects on a loop — HUD scripts and status systems are the most common culprits. Temporarily disable other scripts to isolate.
Why am I getting crafting table errors in my drug script?
Crafting errors come from item name mismatches between the crafting recipe config and your inventory system's item registration. The item key must match exactly — including capitalisation and underscores. Copy item names directly from your shared items file instead of typing them. If names match but crafting still fails, the player may lack the required ingredient in their inventory, or the output item isn't registered at all.
