Koja Scripts

Troubleshooting

Fixes for common koja-mdt problems such as no access, blank UI, missing photos, web portal address, voice and jail integration.

Troubleshooting

Turn on Config.Debug = true and restart the resource to get extra lines in the server console. Check the F8 console for client errors.

Opening the MDT

You don't have access to the MDT.

The player's framework job is not listed in any department. Open shared/departments.lua and add the job name to the jobs list of the right department. Job names are case sensitive and must match the framework job exactly. A job can belong to only one department. Restart the resource after the change.

Go on duty to use the MDT.

Config.Open.allowOffDuty is false. Either set it to true, or have the player go on duty first (/mdtduty or the dashboard toggle). With Config.Duty.syncWithFramework on, the framework job duty is changed as well.

You need a tablet to open the MDT.

Config.Open.requireItem is true and the player has no Config.Open.item (default mdt_tablet). Add the item to your inventory resource, see Installation, or set requireItem to false.

The key or command does nothing
  • Dead players cannot open it unless Config.Open.allowWhenDead is true.
  • With Config.Open.vehicleOnly it only opens in an emergency class vehicle.
  • It does not open while the pause menu is active.
  • Config.Open.command or Config.Open.keybind may be empty.
  • The key can be rebound by the player in the FiveM key bindings. Another resource may use the same key.
A page is missing or shows no permission

The player's access level does not include the permission for that page. See the permission list in Departments and permissions. Pages without permission are hidden. EMS and fire levels do not include citizens.view or incidents.view by default.

Suspended officer

A member can be suspended from their profile by ranks with roster.suspend. A suspended member is limited in the MDT. The same rank can reinstate them.

Blank or broken interface

The tablet opens but is blank or grey
  • Check that you installed the release zip, which contains web/build/index.html. A plain source checkout without the built interface shows nothing.
  • Restart the resource and the client (the NUI cache can hold an old build).
  • Look at the F8 console for NUI errors and at the server console for a failed start. The resource will not start without oxmysql and koja-lib.
  • If the resource is not listed as started, check the order in server.cfg: oxmysql, framework, koja-lib, then koja-mdt.
The interface is in the wrong language

See Translations. Players can have their own language set in Settings. Config.Locale is only the default.

Lists are empty (no people or vehicles)

The framework bridge returns nothing. Check the console banner for the detected framework. If koja-lib reports a framework that is not esx or qb, you need to fill in the Custom functions in editable/server/framework.lua, see Integrations. Also make sure your characters and vehicles live in the standard framework tables.

Database

migration statement failed in the console

A statement of koja-mdt.sql failed. Check that oxmysql is connected and the database user can create tables and alter tables. The message includes the SQL error. Statements are CREATE TABLE IF NOT EXISTS, so you can fix the cause and restart.

Admin panel job editing is missing

Job editing only works on ESX and needs the jobs and job_grades tables. On other frameworks edit jobs in your framework.

Photos

No Take a photo button

The button needs all of these: Config.Camera.enabled, a non-empty Config.Camera.uploadUrl and the screenshot-basic resource started. You can always paste an image link by hand.

Selfie does not work

The selfie needs screenshot-basic. Without it the server says it needs the resource. Profile pictures taken with /mdtphoto use the game's own head shot and work without it.

Upload succeeds but no image appears

The upload response is searched for a link in these places: Discord attachments, files[0].url, data.url, url and link. Use an endpoint that returns one of these, and check Config.Camera.uploadField matches what the endpoint expects.

Selfie is rejected

The server console prints selfie from X rejected: <reason>, where X is the player id. The reason is too_large when the image is over the size limit and invalid when it is not a valid webp, png or jpeg data URL. If the picture is too big, raise Config.Avatars.selfie.maxLength or lower Config.Avatars.selfie.size and Config.Avatars.selfie.quality. A selfie taken before Config.Avatars.selfie.cooldownSeconds has passed shows a cooldown notification instead.

Web portal

/mdtweb says the portal is disabled

Config.Web.enabled is false.

/mdtweb gives a code but no address

The message says to ask the staff for the web address when no URL can be built. Fix it in one of these ways:

  • Leave Config.Web.relay.enabled = true. The server must be able to open an outgoing HTTPS connection (port 443) to the relay address in Config.Web.relay.url.
  • Set Config.Web.publicUrl to your own address.
  • Make sure the web_baseUrl convar is set (it is normally set by FXServer when the server has a license key).
The address does not open
  • Direct access uses the FXServer HTTP port, normally 30120, at the path /koja-mdt/ (the resource name). The TCP port must be open in your firewall and forwarded on your router.
  • Behind a reverse proxy, point it to http://127.0.0.1:30120/koja-mdt/, set Config.Web.publicUrl and Config.Web.trustProxyHeaders = true.
  • If you renamed the resource folder, the path changes with it.
  • Cross-origin setups need the origin in Config.Web.allowedOrigins.
The code is rejected

Codes are single use and valid for Config.Web.loginCodeMinutes minutes (default 10). Request a new one with /mdtweb. There is a 10 second cooldown between requests. The player needs a department job unless Config.Web.allowCitizens is on.

Actions say you are not in game

Responding to calls, sentencing, hiring a nearby player and the duty toggle need a character in the game. They are not available from the web portal while the player is offline.

Dispatch and voice

The dispatcher voice does not play
  • Config.DispatchVoice.enabled must be on, and the officer must be on duty.
  • The officer can switch it off in Settings. Use the Test button there.
  • Calls are only read up to the priority threshold in Config.DispatchVoice.minPriority.
  • Individual announcement types can be off: see Config.DispatchVoice.announce (closed calls are off by default).
  • Voice clips exist for English and Polish. Another Config.DispatchVoice.language uses speech synthesis if the browser has a voice for it, otherwise only radio beeps.
  • Announcements older than staleSeconds are skipped, and the queue is limited by maxQueue.
Players do not receive a call

Calls only go to departments that match the call. A call without a target goes to law enforcement. EMS and fire departments need the call to target them (for example with the jobs or departments fields of the CreateDispatch export). Non-field departments (field = false) never receive calls. /911 and /311 need a message after the command and have a cooldown of Config.Dispatch.publicCooldown seconds.

The panic key does nothing

Config.Dispatch.panicKey may be empty, the cooldown (panicCooldown) may still be running, or the player has no MDT department.

Gunshots do not create a call
  • On-duty police do not trigger alerts by default (Config.Dispatch.gunshots.ignoreOnDuty with ignoreJobs). Test with a civilian job or turn the option off.
  • Silenced weapons (ignoreSilenced), the weapons in ignoreWeapons and the places in ignoreZones (gun ranges) are ignored.
  • The alert is delayed by 3 to 8 seconds (reportDelay), so the call is not instant.
  • A player triggers at most one alert per cooldownSeconds (30), and shots close to a recent alert (mergeRadius, mergeSeconds) are merged into it.
  • Config.Dispatch.enabled and Config.Dispatch.gunshots.enabled must both be on.

Sentencing, jail, fines

The fine is not taken

Integrations.Fine takes money from Config.Processing.fineAccount and falls back to cash. If both are too low, processing fails unless Config.Processing.allowNegativeBalance is on. By default the suspect must be online and within Config.Processing.maxDistance.

The player is not jailed

Check Config.Processing.jailSystem. With 'auto' the first supported jail resource that is started is used. If none is, the MDT only fires koja-mdt:server:jailPlayer, which you can handle in your own script. Add your own jail script as described in Integrations.

The jail record stays open or closes too early

Config.Custody.secondsPerMonth should match your jail script. If the script reports its own releases, add it to Config.Custody.trackedSystems so the clock does not close the record.

Impound does not move the vehicle

The garage fallback needs the framework columns owned_vehicles.stored (ESX) or player_vehicles.state (QB). Otherwise the MDT only records the impound and sets the flag. Set Config.Custody.impoundSystem to your resource, or add an adapter.

Items

Using the citation or document does nothing

The item must exist in your inventory with the exact name from Config.Citations.item or Config.Forms.item, and be usable. For ox_inventory the item needs server = { export = 'koja-lib.useItem' }, see Installation. Citations need metadata support; without it the latest citation of the player is shown.

You don't have a body camera

Config.Bodycams.requireItem is on and the officer has no bodycam item. Add the item or turn the option off.

ANPR and cameras

The ALPR panel does not show

The vehicle must be one of Config.Anpr.vehicle.models or an emergency class vehicle (allowEmergencyClass). The officer must be on duty (Config.Anpr.requireDuty) and have a law enforcement department. The default toggle key is F10.

I cannot place CCTV cameras

Camera placement requires the koja-mdt.cameras ace (Config.Cameras.adminAce) and the MDT officer must not be suspended.

Demo and admin

/mdtdebug says no permission

The player needs one of the aces in Config.DebugTools.aces, see Demo mode. If Config.DebugTools.enabled is false, the command does not exist.

The Admin panel is not visible

Give the player the koja-mdt.admin ace, or a rank with admin.view or admin.manage. Remember that command only works when Config.Admin.allowCommandAce is true.

Players are kicked

If Config.Security.dropAfterFlags is above 0, players who repeatedly send forbidden or flooding requests are removed with Config.Security.dropMessage. The default 0 never kicks. A legitimate player hitting a rate limit just sees the request rejected for a moment.

Still stuck

Collect the server console output at start and any client F8 errors, plus your Config.Debug output, and contact support with the resource version from fxmanifest.lua.