Troubleshooting

Diagnose interface, purchase, financing, world, admin, database, and email issues in Oxide Dealerships.

This guide is organized by the part of the resource the problem shows up in. Find your symptom, then work through the solutions in order — they're listed most-likely-fix first.

Interface Issues

The catalog or admin panel is blank or black

Symptoms:

  • You interact with the greeter and choose Browse Catalog, but the screen is blank, black, or shows nothing.
  • The admin dashboard or management tablet opens to an empty box.

Solutions:

  1. Build the interface. This is by far the most common cause. The visual interface ships as source code and must be built once. Open the resource's web folder in a terminal and run:

    npm install
    npm run build

    After it finishes, confirm a web/dist folder now exists inside web, containing index.html and an assets folder.

  2. Restart the resource. After building, restart oxide-dealerships (or restart the server) so it picks up the freshly built files.

  3. Confirm the build actually completed. If npm run build showed errors in red and stopped, the web/dist folder may be missing or incomplete. Re-run it and read the output — usually it means Node.js needs to be installed or updated.

Notes:

The 3D vehicle preview shows nothing (empty showroom view)

Symptoms:

  • The catalog list loads, but the 3D preview area behind it is empty — no car appears.

Solutions:

  1. Restore the default preview coordinates. The preview spawns a car at a hidden underground spot defined by Config.CatalogScene in shared/config.lua. If those coordinates were edited to somewhere blocked or invalid, the preview car has nowhere to appear. Reset Config.CatalogScene.ground, .sea, and .air to their shipped values.

  2. Restart the resource after changing the config so the new coordinates load.

Notes:

  • This is an advanced setting. Most servers never need to touch it — leave it at the defaults unless you know you want a custom showroom location.

Purchase Issues

A purchased car isn't in the player's garage

Symptoms:

  • The player buys a vehicle, the money is taken, but the car doesn't show up in their garage afterward.

Solutions:

  1. Confirm the framework's garage system is running. The car is saved into your framework's vehicle ownership system through o-link. If your garage resource is stopped or misconfigured, owned cars won't appear even though the purchase succeeded.

  2. Buy a test vehicle and check the logs. Watch the server console for errors at the moment of purchase. If you run a logging resource connected to o-link (such as oxide-logger), the purchase and the vehicle registration are recorded there, which shows whether the ownership write happened.

  3. Check that your garage reads the same ownership table your framework uses. oxide-dealerships writes ownership the standard way for your framework — a custom garage that reads a non-standard table may not see it.

Notes:

  • The vehicle does spawn in the world at purchase. Driving it into a garage and pulling it out again is a good way to confirm ownership saved correctly.

Paying with an item didn't add money to the dealership

Symptoms:

  • A customer paid with an item-based currency (such as a VIP token), got the car, but the dealership's balance didn't go up and the salesperson earned no commission.

Solution:

This is expected behavior, not a bug. Item-based payment methods (set with type = 'item' in shared/config/payments.lua) are treated as a "sink": the item is consumed and the car is granted, but no money is added to the dealership's reserve and no commission is paid. Only money-based methods (cash, bank, and other type = 'money' accounts) credit the lot and pay commission.

Notes:

  • If you want a payment method to credit the dealership and pay commission, make it a money method backed by a framework account, not an item.

A promo code is being rejected

Symptoms:

  • A player enters a coupon code at checkout and it's refused.

Solutions:

Work through the possible reasons the code is invalid:

  1. The code was mistyped or doesn't exist. Checkout looks the code up exactly as it was created — anything that doesn't match an existing code simply comes back as invalid.

  2. The code is used up. A coupon can have a total usage cap and a per-player cap. If either is reached, it stops working. The player may have already used it the maximum number of times.

  3. It's expired. Coupons can have an expiry date.

  4. Wrong dealership. A shop-scoped coupon only works at the dealership it was created for, not everywhere. A global coupon works everywhere.

  5. It doesn't apply to this vehicle. A coupon can be restricted to specific models or categories, or set to not work on financed purchases.

Notes:

  • Owner-created coupons only exist if Config.Coupons.allowOwnerCreated is true (it's false by default). When it's off, the Promotions app is hidden from owners.

Financing Issues

Finance payments aren't being deducted

Symptoms:

  • A player has an active loan, but payments don't seem to come out, or the loan is racking up missed payments.

Solutions:

  1. Check the player's bank balance. Payments are pulled automatically from the bank account (Config.Payments.financeAccount, default bank). If the bank balance is too low when a payment is due, that payment is counted as missed — the system can't take money that isn't there. Payments are only collected while the player is online; by default a payment that falls due while they're logged out just pushes the due date forward (see Config.Finance.missWhileOffline).

  2. Confirm the scheduler is running. Payments come due on a timer (Config.Finance.paymentIntervalMinutes, default 60 minutes). A loan won't charge before its first interval has passed. To test without waiting, an admin can fast-forward a contract with /dealership financeadvance <plate>.

  3. Check the activity logs around a due time. If you run a logging resource connected to o-link (such as oxide-logger), every payment attempt and its result (paid or missed) is recorded there.

Notes:

  • Remind players that financing draws from the bank, not cash — keeping bank funds topped up avoids missed payments.

A vehicle was repossessed unexpectedly

Symptoms:

  • A player's financed vehicle was taken away and they don't understand why.

Solutions:

  1. Check the missed-payment count. A loan defaults and the car is repossessed after Config.Finance.maxMissedBeforeDefault missed payments (default 3). Each time a payment is due and the bank can't cover it, the miss count goes up. You can inspect the missed_count column for that plate in the dealership_financing table.

  2. Confirm the player kept their bank funded. Three missed payments in a row almost always means the bank account was empty at each due time. (Offline time doesn't cause misses by default — loans pause while the player is logged out — unless you've set Config.Finance.missWhileOffline = true, in which case being offline at three due times is enough.)

  3. An admin may have forced it. The /dealership forcerepo <plate> command repossesses immediately. Check whether staff used it.

Notes:

  • After repossession, the vehicle re-lists as a used unit at Config.UsedPriceDiscount (65%) of the original loan amount, keeping its real plate. Its modifications carry over only when your framework's vehicle system shares them with the bridge — in most setups the used unit re-lists at factory specification.

World & Display Issues

The greeter NPC isn't showing up at a dealership

Symptoms:

  • A dealership has a blip, but there's no NPC to interact with.

Solutions:

  1. Place the greeter. A dealership created without a greeter has nowhere for one to spawn. Stand where you want it and run /dealership setgreeter <shopId>. The greeter moves to your exact position and heading.

  2. Don't look at the lot zone. The greeter is independent of the zone — the zone only gates the management tablet and on-duty checks. A missing zone won't hide a greeter; a missing greeter position will.

  3. Check for a conflicting resource. Another targeting or NPC resource placing something at the same spot can hide or overlap the greeter.

The showroom showcase card won't appear

Symptoms:

  • Holding the key while looking at a display car shows no stat card.

Solutions:

  1. Confirm the feature is on. Config.ShowcaseHud.enabled must be true in shared/config/showcase_hud.lua.

  2. Hold the right key. The default is Left Alt (Config.ShowcaseHud.holdKey = 19). Hold it — don't tap it.

  3. Get close enough. The card only shows within Config.ShowcaseHud.maxDistance (8 meters) and needs a clear line of sight to the car.

  4. Look at a display car. The showcase only works on showroom display vehicles (the cars parked on the floor), not on cars in the catalog preview or vehicles players are driving.

The Luxury dealership is missing

Symptoms:

  • You expected a fifth dealership at Rockford Hills and it isn't there.

Solution:

This is intentional. The Luxury Vehicle Shop is shipped disabled because it needs a custom map (MLO) at Rockford Hills to look right. To enable it, follow the Luxury dealership step in the Installation guide.

Admin & Setup Issues

Admin commands do nothing, or say "no permission"

Symptoms:

  • Typing /dealership or any subcommand replies "You do not have permission," or seems to do nothing.

Solutions:

The resource asks o-link whether you're an admin, and the answer depends on your framework:

  1. QBCore / QBX: You need the ACE command permission. Add this to your server.cfg and restart, then make sure your account is in the admin group:

    add_ace group.admin command allow
  2. ESX: You need to be in an ESX admin group (such as admin or superadmin) on your account. Set it through your admin menu or in the users database table.

  3. Test it. Run /dealership list — as a recognized admin it prints your dealerships; otherwise it says "You do not have permission."

Notes:

"Unknown column" or similar database errors after updating

Symptoms:

  • After updating to a new version, the console shows errors about an unknown column or a missing field.

Solutions:

  1. Run any upgrade files that came with the update. When an update changes the database, it ships numbered upgrade files in a sql/migrations/ folder and the changelog (CHANGELOG.md) tells you which ones to run. Import them in numerical order. Re-running install.sql does not add new columns to existing tables.

  2. Restart the resource after running the upgrade files.

Notes:

  • There are no separate upgrade or migration SQL files — sql/install.sql is the complete schema.

No emails are arriving (receipts, contracts, reminders)

Symptoms:

  • Toast notifications appear, but players never get the phone email receipts, finance agreements, or reminders.

Solutions:

  1. You need a phone resource bridged through o-link. Emails are sent through the o-link phone bridge. If no phone resource is connected, no emails send — but everything else (the purchase, the toast notification, the loan) still works normally. This is expected, not a fault.

  2. Check the email toggles. In shared/config/email.lua, Config.Email.enabled is the master switch, and there are per-type switches (receipts, financing, employment, sellerCommission). If a type is turned off, those emails won't send.

  3. The recipient must be online. An email needs the player online at the moment it's sent; offline players are skipped.

Notes:

  • Emails are a bonus "paper trail." The on-screen toast is the instant confirmation and always works regardless of whether emails are set up.

General Debugging

What Config.Debug does

Open shared/config.lua and set:

Config.Debug = true

Restart the resource. This draws each dealership's lot zone outline on screen in-game, so you can see exactly where its boundary sits — useful when the management tablet or on-duty commission checks don't behave the way you expect. It does not add extra console output. Turn it back off (false) on a live server when you're done.

Server-side activity logs

Purchases, finance payments, repossessions, and admin actions are reported through the o-link logger bridge. If you run a logging resource connected to o-link (such as oxide-logger), every one of these events is recorded with its details — that's the place to look when you need to see what actually happened during a purchase or a payment attempt.

Getting Help

If none of the above solves your issue:

  1. Reproduce the problem once so it's fresh.
  2. Check your server console (and your logging resource's output, if you run one) for error messages around the time it happens, and copy them down.
  3. Note your framework (QBCore, ESX, or QBX) and which step or feature the problem appears in.
  4. Contact Oxide Studios support with those details.