Troubleshooting
Symptom-based fixes for Tommy's Radio — connection, audio, microphone, access, 911, dispatch panel and install errors.
Find your symptom below. Before asking for help, run tradio_diag — it is the one thing worth pasting.
The radio can't connect
If players cannot connect, it is a startup problem, not a firewall one. A panel that will not load in a browser is different — see The panel does not load in a browser.
Step 1: read the startup lines
With exposeWeb = false, a healthy start prints one line. With exposeWeb = true the banner's Panel row carries the URL browsers and satellites get.
[Radio-Server] Radio ready over FiveM net events; web exposure disabled (no HTTP listener or tLib registration)
Step 2: check the one port that exists
tLib owns the public port. Open tlib_http_port, and leave tlib_http_public_url unset to auto-detect. Delete any leftover serverPort; serverAddress became hostServerUrl, the host's URL, read only by satellites.
set tlib_http_port 7777
set tlib_http_public_url "http://203.0.113.10:7777"Step 3: run the health check (web installs only)
Only when exposeWeb = true or isSatelliteServer = true.
curl http://127.0.0.1:7777/dispatch/api/health| Result | Next |
|---|---|
JSON with "serviceName":"tRadio" | Healthy. The problem is outside the machine — Step 4 |
Connection refused | tLib is not listening. Check it started, and check tlib_http_port |
| HTTP 404 | tRadio never mounted. Look for tLib refused the '/dispatch' mount |
| JSON naming another service | It owns tLib's port. Move it, or change tlib_http_port |
boundPort is internal and changes every restart. serverUrl is what browsers get. configReady: false means no configuration has arrived — wait, then look for Lua errors. Probe loopback, not your public IP: many hosts cannot route a machine back to its own address.
Port 7777 reachable on localhost but public probe failed from this host — likely hairpin-NAT
or split-horizon DNS. Verify from a remote client; if players connect, this warning is cosmetic.
Step 4: get tLib's port opened
Something between your browsers and the machine blocks it. Confirm from outside with portchecker.co, or open http://YOUR_IP:PORT/dispatch/api/health on mobile data.
On a hosting panel: add the port under Network, Ports or Allocations — not 30120 or 40120. Match tlib_http_port and tlib_http_public_url to it, then restart the entire server: restarting the resource does not bind a new allocation.
On a VPS:
sudo ufw allow 7777 && sudo ufw reload # Ubuntu / Debian
sudo firewall-cmd --permanent --add-port=7777/tcp && sudo firewall-cmd --reload # CentOS / RHELnetsh advfirewall firewall add rule name="tLib" dir=in action=allow protocol=TCP localport=7777Connection and startup messages
Could not connect to the radio voice server names its own cause. Read the text after the colon.
| Message | Cause and fix |
|---|---|
radio transport is not ready | The radio server never finished starting |
authToken is not configured on the server … | Set a strong authToken and restart |
serverUrl unresolved … | Check hostServerUrl on a satellite, tlib_http_public_url on a host |
the voice server is not listening on port … · Failed to connect to radio server… | Legacy socket path. Look for a bind error earlier; by default useLegacySocketTransport should be false |
useLegacySocketTransport=true requires exposeWeb=true | Set exposeWeb = true, or the transport to false |
Web bind failed, in-game radio remains available | Not an outage — browser panels only, unless this is a federation host |
tLib is not started / tLib refused the '/dispatch' mount | ensure tLib must precede ensure tRadio, and tLib must be the release zip |
Could not get a free loopback port (EADDRINUSE) | Ephemeral ports exhausted. Restart FXServer |
A conflict on the public port is a tLib matter: change tlib_http_port and tlib_http_public_url, finding the offender with netstat -ano | findstr :7777.
The radio server never finished starting
A red block, and a Status row reading Radio server did not start. If an earlier startup error was printed, that earlier message is the one to act on. Otherwise check Lua errors earlier in the console, whether tLib started before tRadio, and whether server/dist/bundle.js survived the upload.
One player can't connect, everyone else is fine
Compare the console during their failed attempt with a working player's. On the default transport, treat it as an access problem — see The radio won't open at all. On the legacy socket path, have them try a hotspot. If several players behind one proxy drop together, see Behind a reverse proxy: without the trusted-proxy setting, every player is rate-limited as one client.
The radio drops mid-session and reconnects itself
Error: Connection lost… and its variants mean the link dropped, PTT was pressed while it was down, or a retry was refused. Connection lost. Radio powered off. means retries ran out — five quiet, then ten noisy. Not permanent: powering the radio back on gives a full set, with no relog.
A single burst is normal; only a repeated pattern matters, and a congested link produces them while the game itself seems fine. If everyone drops at once, read Step 1 again. If they drop roughly a minute apart on nginx, check proxy_read_timeout.
The radio powers on, then switches itself off while staying visible
Set Log Level to Debug (4). Have one affected and one working player run /tradio_debug connection, then reproduce a power-on within two minutes — F8 must print trace-enabled-120s. Collect both F8 logs with the NUI build line, plus the server's [connection-trace] output. An empty battery also powers the radio off at the next tick.
The radio won't open at all
F6 does nothing, and F8 shows radio keybind blocked: server has not granted radio access.
- Does the player have a codeplug?
Config.codeplugGrantsmust grant one, with the key matching a codeplug ID exactly. Nothing falls back - Is a grade threshold excluding them? A
jobsentry is a minimum grade - Is the item requirement on? With
Config.requireItemset, they must carry that item - Did their job change? Call
exports['tRadio']:refreshNacId(source), or leaveautoRefreshOnJobChange = true - Does the codeplug have allowed models? With none, there is no radio to render
codeplugGrants changes need restart tRadio. radio keybind blocked: NUI engine not ready yet means the UI is still loading.
Using the radio item doesn't open the radio
"No such export RegisterUsableItem in resource ox_inventory"
That export has never existed in ox_inventory, and tRadio does not call it — another resource is asking. If the line names tRadio, update.
Using the item does nothing at all
Look for tRadio's own message first. If it could not prove any registration method would fire, it prints a boxed block with the items.lua line to add and a Detected: summary. That block is the answer. Otherwise add the route by hand — no exports, no minimum version:
['radio'] = {
label = 'Radio',
client = { event = 'tradio:client:openRadio' },
},The ox_inventory usingItem hook requires v2.43.0 or newer. On an ox bridge to ESX or QBox, item use can route through the framework; tRadio registers that too. On a fork, implement Config.registerRadioItemUse — see Custom and forked inventories.
Carrying the item and opening it by use are separate: if registration fails, the requirement still works and the keybind still opens the radio.
Every player is denied radio access after enabling the item requirement
A red block says tRadio cannot ask your inventory whether a player carries the item. The check is an access gate, so with no answer it fails closed and denies everybody.
- Set
requireItem = nilif you did not mean to require an item - Set
inventory.systemexplicitly instead of'auto' - On a fork, implement
Config.playerHasRadioItemand setsystem = 'custom'
The radio UI doesn't appear (blank screen)
The cursor appears and game controls stop, but no radio is drawn, and there is no Lua error. The built interface under client/ui/ was damaged in transfer: ASCII-mode FTP and Remote Desktop drag-and-drop corrupt the hashed bundles and the binary vocoders while leaving the folder structure looking normal.
The server console names the damaged files shortly after start, and the player's F8 console prints a matching block a minute after they join.
[tRadio] tRadio's built UI files are missing or damaged:
[tRadio] - client/ui/assets/index-XXXXXXXX.js (truncated — 214 bytes)
[tRadio] - client/ui/p25-imbe_wasm.b64 (empty)
Older releases printed nothing here, so a silent console on one is not evidence the files are intact.
Fix — re-upload the whole folder, then restart tRadio. Unzip the release on the server, set your FTP client to binary, or use SFTP. Do not copy only the file the console named: anything sent in the same session may be damaged too.
No audio
| Symptom | Cause and fix |
|---|---|
| Nobody can hear me and I can't hear anyone | The codeplug lacks the channel. Add it under Channel Access, or grant tradio.connect.{freq} (drop the decimal: 154.755 → 154755) |
| No tones or radio character | Check Transmission Tones, Radio FX and Tone Volume in Settings → Audio & Radio |
| Unwanted bonks, or people talking over each other | Audio & Radio → Half-Duplex. Play Bonk Tone off silences it; Block Transmission on stops the second one |
| P25 sounds duller than analog | Expected — IMBE runs at 8 kHz, telephone bandwidth. Set Mode to Analog for a brighter channel; crackling is not expected |
No scan list or List empty | The codeplug assigns No scan list to that channel or the default — change it, or pick Personal. List empty means nothing to listen to; add channels with ScnL |
Nothing heard, Priority chan, Operating chan | No scanned channel to delete, or the one you hear is protected |
| Scanning seems to turn itself on | Saved state. Only a Stream Deck Toggle Scan key or addListeningChannel turns scan on from outside |
I turned 3D audio on and nothing changed
Because every player starts with earbuds on, and a player wearing earbuds emits nothing — their radio audio is going to their ears, so the people around them hear no radio. Nobody is emitting, so nobody has anything to hear. That default is the inverse of Settings → Audio & Radio → 3D Audio On by Default, which ships off.
Earbuds are emission-only: they decide whether that player's radio is heard by others, and never what the player themselves hears.
- For one player, now:
/tradio→ Sounds → Earbuds, off - For new players: turn 3D Audio On by Default on. It never overrides an existing choice
The master Enable 3D Audio switch must be on for either to matter. If earbuds keep switching back on, the player is wearing a configured earpiece item.
Weak signal doesn't sound like anything
Degradation only starts at 3 bars, and with the shipped towers most players stay between 3 and 5 all session. Reaching 1–2 needs a much higher Falloff Rate or sparse towers; Degradation Intensity does nothing on full bars. Check Signal Degradation is on — it ships off — and Always Full Signal is off.
It does not sound like static. Low signal narrows the band, lowers volume, coarsens the audio and inserts brief dropouts. No hiss is modelled. See Battery and signal.
Robotic, warped, or metallic audio on a P25 channel
| What you hear | Cause and fix |
|---|---|
| Robotic at the start of a session, or a clipped first syllable | Normal. The vocoder is warming up; if clipping is severe, raise PTT Release Delay |
| Metallic buzz or warbling | Mic input is clipping. Lower the level in Windows Sound → Recording → Properties → Levels |
| Dispatch hears clean audio, not P25 | That channel is not P25. Set Mode to P25 Digital — there is no global switch |
| One talker is clean, everyone else is P25 | Their digital encoder failed to start, and an older release fell back to clear voice. Update |
| Talkers cut in and out on a busy server | The listener's game cannot keep up decoding. Update, then run /tradio_debug audio: RX dropped and RX underrun show the loss |
Idle hum, pops, or clicks
Turn Signal Degradation off and listen again. It inserts dropouts at low signal; if that removes the artifacts, lower Degradation Intensity or add more signal towers.
I can't hear my scanned channels
The first three cover almost every report.
- Is scan on? The scan icon lights while it is. Scan on/off is separate from the list
- Is scanning allowed on that codeplug? Codeplugs → Features → Scan
- Is the channel in the list for the channel you are on? The radio scans the list assigned to your current channel — check Codeplugs → Scan Lists
- Is it in Scan Access? Add it, or grant
tradio.scan.{freq} - Otherwise: a nuisance delete (it returns when scan is cycled), or your own PTT and connected channel, which always pause scan audio
- Long scan list? If the console shows
Control-plane rate limit exceeded, raise Control Message Rate Limit (default 120, valid 30–2000, live)
The radio's controls and screen
| Symptom | Cause and fix |
|---|---|
| The floating close button is gone | Removed. Escape returns control to the game and leaves the radio visible; /tradio → Behavior → Hide radio when releasing focus hides it too |
| The text looks small, or an update did not change the size | A saved size beats a model's new default. Use /tradio → Appearance → Reset Position |
| PTT transmits on a scanned channel, or bonks while scanning | That list is set to Talkback. A bonk means the channel is scan-only, or the player is on a federated satellite. Set the list to Selected channel |
Emergency problems
| Symptom | Cause |
|---|---|
| The button does nothing, or gives a short low tone | You clicked instead of holding, the radio is not on a channel, the profile is No emergency, or Emergency Button is off under Codeplugs → Features |
Cooldown | The same player raised one there less than Panic Alert Cooldown ago (15 s) |
| Silent on the radio, visible to dispatch | The profile is Silent. That is intended |
| A dispatcher acknowledged and it did not end | Only Alarm ends on acknowledgment. Alarm + Call needs the button, Clear, or Panic Alert Timeout; Call has no alarm. On a satellite, a host acknowledgment does not reach the unit |
No emergency with a repeating low tone | You moved to a channel with no emergency profile. It is paused — move back, or hold to clear |
My radio's keys moved
Radio screens follow the layout real public-safety portables use. Keys also differ per department if an admin programmed a Home softkey bank — see On-radio buttons.
Microphone not working
| Symptom | Cause and fix |
|---|---|
| Wrong device | Pick the input in /tradio → Sounds → Microphone, or Options → Mic. Closing the radio mid-discovery cancels it |
Mic: No microphones found (refresh) or No microphones detected. (startup) | Windows reported no inputs. Enable the mic in Sound → Input; a disabled device does not count. Bluetooth headsets often show none until connected in the headset profile |
Microphone setup failed. | Found but not openable: another app has exclusive use (close Discord, OBS, Teams, then untick Allow applications to take exclusive control), the device was unplugged, or Privacy & security → Microphone blocks it |
| All audio drops when anyone transmits | Windows ducking, not tRadio. Sound → More sound settings → Communications → "Do nothing", then restart FiveM |
| Bluetooth headset collapses to muffled mono | It switched to its hands-free profile to run its mic. Use a wired headset, a separate mic, or a USB dongle |
| Echo, or others hear themselves | Open speakers. tRadio captures raw — no echo cancellation or noise suppression |
FiveM was denied microphone access
If the player clicked Deny, no device list appears at all. FiveM remembers that answer permanently, per server and per resource. Close FiveM, delete %appdata%\CitizenFX\media_access.json, relaunch, and click Allow. Do not delete the whole cache — it throws away every downloaded server asset, and the answer is in that one file. Renaming the tRadio folder re-prompts everybody.
canTalk is returning false
Voice chat works but the radio doesn't (or the reverse)
Expected, not a bug. Radio PTT uses tRadio's own capture; in-game voice is used only for 911 calls.
Diagnostic commands
Every client diagnostic is a subcommand of /tradio_debug: report (everything, for a ticket), audio (audio context, degradation, buffers, micStreamReady / isRecording), output [deviceId], signal (inputs and resolved level), signalpath (a two-second receive measurement while another player transmits), connection (socket health, plus a two-minute lifecycle trace), coords [lua|json] (copies your position for speakers and towers), and connect <url> (override this client's server address; no argument clears it).
An emergency alert fired and nobody pressed anything
Almost always Man Down, which raises an emergency when a player has been down and motionless long enough. It is off by default, raises whatever the channel's profile programs, and says so in F8:
[tRadio] Man Down: no movement or transmission for 10s (then 15s in warning) —
escalating to the emergency programmed for the channel on 154.755.
Turn it off per player (/tradio → Sounds → Man Down Alarm), per department (Codeplugs → Features → Man Down) or server-wide (Settings → General → Man-Down by Default, which does not clear a player who already switched it on). In the post-alert, Clr silences it until they move.
A conscious player standing still gets the tone and banner and nothing more; only a dead, dying or ragdolled player escalates. If a standing player escalates, update. See Man down.
Wrong channels, zones, or blips
| Symptom | Fix |
|---|---|
| A channel is missing from the radio | Add it to the codeplug's Channel Access, or grant tradio.connect.{freq} |
| A channel cannot be scanned | Add it to Scan Access, or grant tradio.scan.{freq} |
| A zone is missing | Zone access derives from channels. Select one, or grant tradio.zone.{N} |
| No GPS blips for other players | Check all three: the target codeplug under GPS Visibility, GPS Blips in its Features, and Radio Blips in Settings. The player's own GPS toggle must be on |
| A zone vanished from the panel but works in game | Its Hide from dispatch toggle is on |
| Zone ACE grants apply to the wrong zone | tradio.zone.{N} is positional. Deleting or reordering zones shifts every later grant |
A player hears a channel I never granted them
Two frequencies collapse to the same ACE key, because the key drops the decimal point: 1.23 and 12.3 both become 123. The console names the clash once per start.
Every frequency also answers to a precise key with the point as an underscore — tradio.connect.154_755 alongside tradio.connect.154755. Both are checked, so moving a grant to the precise form never takes access away. Never write the point as .: that reads as a deeper namespace and grants nothing.
911 calls
| Symptom | Cause and fix |
|---|---|
/911 says unknown command | 911 Calling is off in Settings → General — it ships off, so a fresh install is the usual reason — or LB Phone 911 Dial-In is on and replaces it. If the phone integration is on but lb-phone is not started, players cannot reach 911 at all |
| Turning 911 off didn't remove the command | Expected. FiveM cannot unregister a chat command, so it stays for connected players — but the server rejects every call |
| Calls never reach the panel | The call is queued. Confirm a dispatcher is logged in and the 911 section is not collapsed. With nobody on the panel, call911NoDispatcherFallback fires |
| The caller can't be heard after accept | 911 calls use in-game voice activity detection, not radio PTT |
Calls don't reach ImperialCAD
tRadio never sends a community ID or API key — it only calls that resource's exports locally. So an invalid community, bad-key or unauthorized error is ImperialCAD's own credential check failing. Check imperial_community_id and imperialAPI, set before ensure ImperialCAD. The failure that is ours names itself, matching the resource name case-sensitively:
ImperialCAD (startup): enabled=true but GetResourceState('ImperialCAD') = 'missing'
(expected 'started') — check that the resource is named exactly 'ImperialCAD' in your
server.cfg/resources folder and has fully started.Dispatch panel
The panel does not load in a browser
Check tLib's port first. With exposeWeb = true the panel is at http://<your server>:7777/dispatch. A port closed on the host or unforwarded in NAT is the most common cause, and the console cannot tell you — test from outside, see Step 4.
| What you see | Fix |
|---|---|
| Nothing served on that port | exposeWeb = false. Set it true and restart |
HTTP 404 at /dispatch | tRadio never mounted. See the startup messages above |
| The hub loads but has no panel entry | showDispatchInHub = false. Visibility only — the URL still works |
| A page loads that is not tRadio | Another service owns tLib's port. Step 3 names which |
Other panel problems
| Symptom | Fix |
|---|---|
| The desktop app shows someone else's server | It points at the demo endpoint. Set Endpoint URL to http://YOUR_IP:YOUR_PORT/ |
| It asks for a NAC ID and I don't have one | It is not generated — set dispatchNacId and restart |
| Microphone doesn't work in the browser | Browsers expose microphone APIs over HTTPS only. Use the desktop app, or a TLS reverse proxy |
| Clicking the shortcut again does nothing | The app is single-instance; it raises the existing window |
No authentication method configured | Neither adminPassword nor discord.adminRoles is set |
| Session expired banner | Admin sessions log out after 30 minutes idle, and a restart invalidates them |
| It says I'm transmitting but nobody hears me | The wrong input device. System default often resolves to a webcam or a silent virtual device. Pick your real microphone in Settings → Microphone |
"Digital audio unavailable" in the panel header
The vocoder that decodes P25 is not working on this panel, so every P25 channel is silent for you. Everything else keeps working. It is per dispatcher: one affected and not another means that machine.
Reload the panel, then reinstall the desktop app: a partial install is the most common cause. Confirm the radio server is reachable and that any proxy or CDN serves .wasm files. If the server's files were re-uploaded recently, the vocoder may be damaged — see The radio UI doesn't appear.
AI dispatcher
A dispatcher that cannot run stays quiet rather than erroring on the air, so read the console first.
The dispatcher never answers anything
All four are settings, not faults.
- The master switch is off. Settings → AI Dispatcher ships off
- The channel is not listed. The Channels field is empty by default, and empty means none
- A human dispatcher is signed on. With Yield to a Real Dispatcher on, the AI stands down
- The wake phrase was not said. Start with
dispatch. Traffic without it is heard but never answered, and the console says so
It is working when the console prints a [Radio-Server:ai] turn: pair — what was heard, and what was done.
Other AI dispatcher problems
| Symptom | Cause and fix |
|---|---|
the API is restricted | FXServer blocks a resource from launching a program. Add add_unsafe_child_process_permission tLib and restart — tLib, not tRadio, starts the engines |
| A missing model in the console | Models are fetched on request, not shipped. Press Download model files, or run tradio_ai_download. If you moved the weights, point Config.aiDispatch.localEngine at them |
| A missing binary in the console | The binaries do ship, so a transfer dropped files. Re-transfer the release .zip |
| Linux: the engine will not start | The binaries need glibc 2.34 or newer (ldd --version). Debian 12 and Ubuntu 22.04 are fine; CentOS 7 and Ubuntu 20.04 are not |
| A hosted provider runs locally anyway | No API key. Keys go in Admin Panel → Credentials; a provider without one falls back and says so |
| Two engines running, or the port is held | Engine sharing matches on server/models/artifacts.json. Swap weights without editing it and each resource loads its own |
| It answers, but the answers are wrong | Usually procedure it was never told, which lives in Config.aiDispatchInstructions. In server/logs/ai-dispatch.jsonl, a draft differing from what aired means a tool rewrote it |
Install and config errors
| Error | Cause and fix |
|---|---|
Could not find dependency tLib for resource tRadio | tLib is absent — not a load-order problem. Download tLib.zip from the releases page, not "Source code", unzip into resources/ as tLib, and put ensure tLib above ensure tRadio |
No such export … in resource tLib | tLib is older than tlib_min_version. Replace it and restart both. If the export belongs to some other resource, that one is a load-order problem |
Syntax error referencing <\1> | A corrupted transfer, or an artifact older than 4752. Use SFTP or binary mode. The same transfer damages the UI and vocoders silently — see The radio UI doesn't appear |
Missing .fxap | Dot-prefixed, so FTP clients hiding hidden files drop it, as does .gitignore |
ERROR: Framework 'esx' failed to initialize. | Every player is denied radio access until this clears. Confirm the resource is running and Config.frameworkResources matches its name |
| The screen locks up: cursor visible, no menu | tLib came from the source download, whose built UI is not in source control. After 15 seconds tLib prints the cause. Replace it with tLib.zip |
The Alrt key is missing or does nothing | Supervisors on a connected conventional channel only; trunked shows Ctrl/Trnk. Supervisor Access on the codeplug or the tlib.admin ACE grants it |
tlib.admin grants in-game supervisor features only — not the web admin panel. There is no "distributor" permission; ignore anyone who says to add one.
To update a Linux artifact: download from the build server, stop the server, delete the cache and alpine folders, run tar -xf fx.tar.xz, and restart.
"Save failed — Write failed" in the admin panel
A save fails with EACCES: permission denied or EROFS: read-only file system. Some managed hosts ship the resource directory read-only. tRadio tests this at startup and prints a banner naming the error.
data.json and data.json.bak must be writable, so it is the folder that needs permission for the account the server runs as:
chown -R fivem:fivem /path/to/resources/tRadio && chmod -R u+w /path/to/resources/tRadioIf the host cannot be made writable, edit data.json by hand: stop the server, download it, validate the JSON, upload in binary mode, start.
Changes in the admin panel aren't applying
Almost everything applies live. The exceptions are marked Restart required: 911 Calling, the Callsign Command name, and LB Phone 911 Dial-In. Anything edited in config/config.lua, sv_functions.lua or cl_functions.lua also needs restart tRadio.
Getting more detail
tradio_diag — the one thing to paste when asking for help
Run tradio_diag in the server console. It prints tRadio's and tLib's versions, which config layers are in effect, the state of every dependency, and anything the startup check reported.
It is pre-redacted: authToken, adminPassword, discord.clientSecret, discord.botToken and every AI provider key report as set or not set. The output is safe to paste in public. Your config.lua is not. Players need the command.tradio_diag ACE; the console always can.
add_ace group.admin command.tradio_diag allowtRadio also checks config/config.lua at startup and reports every problem at once, naming the key and what it expected.
Log level
Raise Log Level in Settings → General. It applies immediately: 0 errors, 1 warnings, 2 minimal, 3 normal (the default), 4 debug, 5 verbose and measurably costly.
Reproduce at level 4 or 5, then look for [tRadio]-prefixed lines. Connection failures appear at startup; audio problems only when someone transmits. Set it back to 3 afterward.
Still stuck? Post in the FiveM community thread with the console error block, your redacted config.lua, the level 4 output, and your framework.
Next steps
- Everything the radio can be told to do: Configuration
- Operating the radio and the panel: Usage
- Integrating with your own scripts: API Reference
Tommy's Radio
Still stuck? Support can answer it directly.
Was this page helpful?
TIMMYG Studios