Skip to Content
ScriptingResource Storage & Sandbox

Store small resource settings without escaping the sandbox

Use LoadResourceFile and SaveResourceFile for a small JSON document owned by your resource. Keep the filename fixed, validate the data, and check the write result. Use a database for balances, inventory, concurrent updates, or records that need transactions.

The example below stores an informational maintenance banner. It does not enforce admission, take a server offline, or replace a backup system. Only the server console can change it.

Create a server-only settings resource

Create resources/[local]/doc_settings/fxmanifest.lua:

fx_version 'cerulean' game 'gta5' server_script 'server.lua'

Create settings.json:

{"banner":"Welcome to the development server"}

Create server.lua:

local resourceName = GetCurrentResourceName() local filename = 'settings.json' local settings local function valid(value) return type(value) == 'table' and type(value.banner) == 'string' and #value.banner <= 160 and not value.banner:find('%c') end local raw = LoadResourceFile(resourceName, filename) if raw and #raw <= 4096 then local ok, decoded = pcall(json.decode, raw) if ok and valid(decoded) then settings = { banner = decoded.banner } end end if not settings then print('[doc_settings] Invalid settings.json. Repair it before updating the banner.') end RegisterCommand('docbanner', function(playerId, args) if playerId ~= 0 then return end -- Console only, even if a player has ACE access. if not settings then return end if #args == 0 then print(('Banner: %s'):format(settings.banner)) return end local candidate = { banner = table.concat(args, ' ') } if not valid(candidate) then print('Use at most 160 bytes, without control characters.') return end local encoded = json.encode(candidate) if not SaveResourceFile(resourceName, filename, encoded, #encoded) then print('[doc_settings] Write failed. The in-memory setting was not changed.') return end settings = candidate print('Banner saved. Restart the resource and run docbanner to verify persistence.') end, true)

Do not list settings.json under files, which would make it part of the client download. In the server console, run refresh, ensure doc_settings, then docbanner Maintenance starts at midnight. Run restart doc_settings and docbanner; the banner should persist.

What the sandbox allows

The official sandbox documentation  defines resource filesystem boundaries. The safe default is to write within the current resource; cross-resource writes are restricted. SaveResourceFile is not a way around those restrictions. An access-denied error is a reason to inspect the ownership and destination, not disable protections or shell out.

Never accept a filename, resource name, directory traversal, or source code from a network event and pass it into a file-writing function. Do not store executable Lua or JavaScript as user-editable configuration. Keep credentials server-side and out of streamed/shared files.

Storage needBetter fit
Small resource-owned settingsValidated JSON file, backed up with server data
Small resource key/value preferencesResource KVP APIs; choose the correct client or server context
Shared balances or inventoryDatabase with transactions and server-side validation
A setting clients need to displayPublish only the safe value through a deliberate API or event, not the complete file

Test and deployment limitations

Test invalid JSON, a missing file, a too-long banner, and a read-only resource directory. A player entering docbanner must never be able to mutate configuration. Keep a backup of the file before changing deployment permissions.

This example has one writer and synchronous updates, with no yield between reading the current value and saving its replacement. It is not a transactional storage layer or a crash-safe atomic replacement scheme. A crash or interrupted filesystem write can still damage a file. The next startup refuses an invalid configuration rather than silently overwriting it.

In containers or artifact-based deployments, a file written into a disposable resource directory may disappear on redeploy. Mount persistent storage deliberately and test both restart and redeploy behavior. Continue with backups, database access, and server permissions.