FiveM Docs
Addons

esx_garage

Configure esx_garage 2.0 for ESX Legacy: garages, impound lots, job access, settings, server exports like registerGarage and impoundVehicle, and fixes.

esx_garage is the ESX Legacy garage and impound system. Players park owned vehicles at garages, take them out again through a React UI, favorite, rename or transfer them, and pay a fee to recover vehicles from an impound lot. Version 2.0 replaced the old marker-based config completely, so configs from older versions do not work.

Overview

Resourceesx_garage (version 2.0.0)
Sideclient + server, NUI (web/dist)
Dependenciesesx_lib, es_extended, oxmysql
Optionalesx_hud (mileage shown in the UI)
Dataowned_vehicles plus columns parking, pound, custom_name, is_favorite, last_used, mileage; table esx_garage_migrations

Features in-game:

  • Garages with an entry point (opens the menu), an optional store point and an optional NPC.
  • Impound lots with a per-lot fee. The fee is taken from cash first, then from the bank.
  • Paginated vehicle list with search and filters (stored, impounded, favorite).
  • Rename and favorite vehicles, transfer a stored vehicle to a player within 10 m.
  • Optional "give keys" hook for a key script.

Vehicle state

storedparkingpoundMeaning
1garage id or NULLNULLParked in a garage
1NULLimpound idImpounded
0NULLNULLOut in the world

A vehicle that is out (stored = 0) but whose entity no longer exists can only be recovered at an impound, never at a garage. Before respawning it the server deletes every live entity with that plate, so it cannot be duplicated.

Installation

Database

Nothing to do on an existing server: on start the resource adds missing columns and indexes, converts legacy stored = 2 rows to the new impound state and records version 1.16.0 in esx_garage_migrations. For a fresh or manual install you can import esx_garage.sql; every statement is guarded, so it is safe to run again.

Ensure the resource

server.cfg
ensure oxmysql
ensure esx_lib
ensure es_extended
ensure esx_garage

Configuration

Config.Settings

KeyDefaultDescription
interactionDistance3.0Distance to a garage or impound point to interact.
restrictToGaragefalseOnly allow retrieval at the garage stored in parking. NULL or removed garages count as "any garage".
defaultImpoundFee400Fee for impound lots without their own cost.
vehicleKeysfalseShows the give keys button and enables the esx_garage:giveKeys callback.
storeMarkerOnlyInVehicletrueOnly draw the store marker while sitting in a vehicle.
showMarkertrueDraw ground markers at the points.
vehiclesPerPage30Default page size of the vehicle list.
maxVehiclesPerMenu100Largest page size a client may request (hard capped at 100).

Config.Locale defaults to GetConvar('esx:locale', 'en').

Config.Garages

A list of garages. Defaults: vespucci_boulevard and san_andreas_avenue.

FieldTypeDescription
idstringUnique id, stored in owned_vehicles.parking. Do not rename it once used.
labelstringDisplay name and blip label.
type'public' | 'job' | 'gang' | 'impound'Passed to the UI. Access is not derived from it; use access.
entryPointvector3Opens the menu.
storePointvector3?Where vehicles are parked.
spawnsvector4[]Spawn positions; at least one.
blip{ sprite, scale, color }?Map blip.
ped{ model, z?, heading?, snapToGround? }?Optional NPC.
access{ jobs?, authorize? }?jobs maps job name to minimum grade. authorize(source, garage) is a server-side function that returns true to allow.
logostring?Image URL shown in the menu header.
colorstring?Hex accent color for the menu.
poundstring?Linked impound id.
config.lua
Config.Garages[#Config.Garages + 1] = {
    id = 'mrpd',
    label = 'Mission Row PD',
    type = 'job',
    entryPoint = vec3(454.6, -1017.4, 28.4),
    storePoint = vec3(447.6, -1021.5, 28.5),
    spawns = { vec4(438.4, -1018.3, 27.7, 90.0) },
    blip = { sprite = 357, scale = 0.8, color = 38 },
    access = { jobs = { police = 0 } },
    pound = 'los_santos',
}

Config.Impounds

Defaults: los_santos, paleto_bay, sandy_shores, each with cost = 3000. The first entry is the default lot for automatic impounds.

FieldTypeDescription
idstringUnique id, stored in owned_vehicles.pound.
labelstringDisplay name.
getOutPointvector3Opens the impound menu.
spawnsvector4[]Spawn positions.
blip{ sprite, scale, color }?Map blip.
pedtable?Optional NPC.
costinteger?Fee; falls back to defaultImpoundFee.

Server exports

registerGarage

exports.esx_garage:registerGarage(garage)

Adds or replaces a garage at runtime and refreshes all clients. Throws (via assert) if id, entryPoint or spawns are missing or invalid. Use it for property or gang garages created by other resources.

server/main.lua
exports.esx_garage:registerGarage({
    id = 'apartment_12',
    label = 'Apartment 12',
    type = 'public',
    entryPoint = vec3(-796.1, 304.4, 85.7),
    spawns = { vec4(-791.6, 300.3, 85.4, 180.0) },
    access = {
        authorize = function(source)
            return exports.my_housing:isTenant(source, 12)
        end,
    },
})

registerGarages

exports.esx_garage:registerGarages(list)

Calls registerGarage for every entry in list.

unregisterGarage

exports.esx_garage:unregisterGarage(id)

Removes a garage by id and refreshes clients. Vehicles parked there remain available at any garage.

getGarages / getImpounds

local garages = exports.esx_garage:getGarages()
local impounds = exports.esx_garage:getImpounds()

Return arrays of all registered garages and impound lots (including runtime registrations).

impoundVehicle

local ok = exports.esx_garage:impoundVehicle(plate, lotId)
NameTypeDescription
platestringPlate of an owned vehicle.
lotIdstring?Impound id. Unknown or nil falls back to the first lot.

Deletes the live vehicle if it exists and marks it impounded. Returns true when the database row is in the impound afterwards. Typical use: a police or tow job command.

server/main.lua
ESX.RegisterCommand('impound', 'admin', function(xPlayer, args)
    local ok = exports.esx_garage:impoundVehicle(args.plate, 'los_santos')
    xPlayer.showNotification(ok and 'Vehicle impounded' or 'Impound failed')
end, false, {
    help = 'Impound a vehicle by plate',
    arguments = { { name = 'plate', help = 'Plate', type = 'string' } },
})

Server events (hooks)

Local server events you can listen to with AddEventHandler. They cannot be triggered by clients.

EventArgumentsFired when
esx_garage:vehicleTransferredsource, targetId, plate, fromIdentifier, toIdentifierA player transferred ownership of a vehicle.
esx_garage:giveKeyssource, plateA player pressed "give keys" (only with vehicleKeys = true).
server/keys.lua
AddEventHandler('esx_garage:giveKeys', function(source, plate)
    exports.my_keys:giveKey(source, plate)
end)

Callbacks

The UI talks to the server through these callbacks. Each is rate limited (1 to 1.5 s) and checks ownership, distance and garage access on the server, so they are safe against spoofed clients. They return { success = boolean, error = string? }.

CallbackPurpose
esx_garage:getGaragesGarages the player can access, plus all impounds.
esx_garage:getVehiclesPaginated vehicle list.
esx_garage:retrieveVehicleTake a vehicle out (charges the impound fee).
esx_garage:storeVehiclePark the current vehicle.
esx_garage:toggleFavoriteToggle favorite.
esx_garage:renameVehicleSet custom_name.
esx_garage:transferVehicleGive a stored vehicle to a player within 10 m.
esx_garage:giveKeysFire the esx_garage:giveKeys hook.

The client event esx_garage:refresh rebuilds blips and points; it is also triggered on esx:playerLoaded and esx:setJob.

Integration tips

  • Vehicles bought in esx_vehicleshop land in owned_vehicles and show up automatically.
  • The garage list does not filter by the vehicle type column, so boats and aircraft appear in every garage. Use separate garages with access if that matters.
  • Despawning an owned vehicle with another script sends it to the default impound. Store it through esx_garage or call impoundVehicle with the right lot.
  • The maxVehicles field from the type annotations is not enforced by the current code.

Common issues

  • Old config does not load: v2 uses Config.Settings, Config.Garages as a list with id/entryPoint/spawns, and Config.Impounds with getOutPoint. Config.DrawDistance, Config.Markers and the old EntryPoint/SpawnPoint keys are gone.
  • no_money at the impound: the player has neither enough cash nor enough bank money for the fee.
  • wrong_garage: restrictToGarage is on and the vehicle is parked elsewhere.
  • model_mismatch or plate_mismatch when storing: the vehicle entity does not match the owned record (for example after a plate change by another script).
  • Every vehicle impounded after restart: expected, see the FAQ below.

Frequently asked questions

Independent documentation

esx-fivem.com is a community project and is not affiliated with the ESX Framework team. Facts on this page were checked against the upstream source. Official resources: docs.esx-framework.org and github.com/esx-framework.
Edit on GitHub

Last updated on

On this page