vrs_permanentid are documented here. The most recent release is at the top.
2026-08-08
Permanent IDs now belong to the player, not the character, and they finally show up where staff actually work: in admin commands and in txAdmin.
Upgrading from 1.0.0? The database migrates itself on first start. Back up first, see Installation.
⚠️ Breaking changes
- One ID per account, not per character. IDs are now keyed on the player’s
licenseinstead of theircitizenid. A player with three characters used to own three IDs; now they own one. - IDs now start at 1000 (
Config.StartId), up from1. This keeps them clear of live server IDs so both can be typed into the same commands without ambiguity. Only affects brand-new installs, existing IDs are never renumbered. - Server exports are online-only and never yield.
GetPermanentIdByIdentifierandGetIdentifierByPermanentIdused to fall back to a database lookup, which could crash the calling resource with “attempt to yield across C-call boundary”, an export cannot yield across a resource boundary. Query thevrs_permanent_idstable directly if you need offline lookups. /idis now owned by this resource. QBox/QBCore register their own/idthat prints the slot number; left alone, both fire on one chat message. The patch to disable theirs is inpatches/.
Added
- Automatic database migration from the 1.0.0 layout. Detects the old schema, keeps each player’s oldest ID, merges their other character rows into it, and moves the unique key from
identifiertolicense. If the migration cannot complete, the resource refuses to assign any ID rather than risk handing every player the same row. patches/, drop-in patches that teach admin commands the permanent ID without editing those commands one by one:ox_lib, theplayerIdargument parser. One file, ~30 commands (/giveitem,/givemoney,/setjob,/revive,/givekeys, …).qbx_core,qb-core,es_extended, the frameworkGetPlayerlookups, for commands that take the id as a plain number.monitor, txAdmin (see below).- Every patch is statebag-based, so it carries no dependency on this resource, has no load-order requirement, and does nothing at all when
vrs_permanentidis stopped.
- txAdmin support, in three places:
- permanent-ID lines in the live console, no patch needed;
- the ID appended to the player name in the web panel and the in-game menu (
monitor/resource/sv_playerlist.lua); - the ID in the panel’s sidebar badge in place of the slot number (
monitor/panel/patch-panel.js). Display only, clicking a player, kicking, banning and spectating still use the real slot number.
Config.MinPid, the number below which a value is always read as a server ID. Published as thevrs_pid_minconvar so the patches can read it without depending on this resource.Config.Console, toggles the permanent-ID lines printed on connect, character load and disconnect.GetPermanentIdByLicense(license)andGetIdentifierBySource(source)exports.- Installation guide, plain-language setup, and a rewritten
patches/README.md.
Changed
- IDs are assigned during
playerConnectinginstead of on character load. They have to exist before the player takes a slot, because txAdmin captures a player’s display name exactly once, atplayerJoining, and never updates it afterwards. A character-keyed ID arrives far too late for that. OnPlayerLoadedno longer assigns anything. It records which character is in play and publishes the character name.- The statebag is re-asserted on character load, since the client is not necessarily connected yet when
playerJoiningsets it. /pidnow works on any connected player, not only ones with a character loaded./findpidreports the account license instead of a citizenid.- Resource restart with players already online now re-adopts them.
Fixed
Duplicate entry '…' for key 'identifier'on character load after upgrading.CREATE TABLE IF NOT EXISTScannot alter an existing table, so the 1.0.0 unique index onidentifiersurvived the upgrade untouched. Made worse on a non-strictsql_mode, where MySQL silently accepted an emptyidentifierinstead of raising an error, quietly creating junk rows. Now handled by the migration.- The temporary source used during
playerConnectingis no longer written into the source-keyed lookup tables, it can differ from the ID the player ends up with, which left stale entries behind. - A failed migration no longer leaves connecting players waiting forever on an internal “ready” flag.
Notes for people who patch txAdmin
monitor is part of FXServer, not your server folder, so both txAdmin patches are erased by every artifacts update. Stock copies are saved alongside each patched file as .stock.bak.After re-applying the panel patch you must restart the txAdmin process itself, restarting the server is not enough, because txAdmin loads the whole panel into memory once at startup. Then hard-refresh your browser (Ctrl+Shift+R): the file keeps its name, so nothing else tells the browser it changed.Initial release
Added
- Permanent, per-character numeric IDs assigned on first login and stored in
vrs_permanent_ids. - Zero-config install. Table auto-created, no SQL file required.
- Framework auto-detection via vrs_bridge (QBox, QBCore, ESX).
- Server-authoritative ID assignment via MySQL
AUTO_INCREMENT. - Replicated statebags:
Player(src).state.vrs_pidandPlayer(src).state.vrs_pid_name. - Commands:
/id,/pid,/findpid,/showids. All renameable / disableable inconfig.lua. - Server exports:
GetPermanentId,GetPermanentIdByIdentifier,GetIdentifierByPermanentId,GetSourceByPermanentId,GetAllOnline. - Client export:
GetMyPermanentId. - ACE permission support (
vrs.permanentid), with QBox/QBCoreadmin/godand ESXadmingroups passing automatically. - Open
locales/*.luafor translations with English fallback. - Escrow-open
config.luaandlocales/*.lua.

