Common problems and how to fix them. If you hit an issue not listed here, please open an issue.
JWT_SECRET must be set on backend startThe backend refuses to start without a JWT secret — any unset value would allow forged tokens. Generate one and put it in .env:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
AGENT_SECRET must be set on agent startSame as above for the server agent. The agent will refuse to start if the secret is blank.
node -e "console.log(require('crypto').randomBytes(24).toString('hex'))"
EADDRINUSE / port already in useSomething else is already listening on port 3001 (backend), 3002 (agent), or 5173 (Vite). Either stop the conflicting process or change the port:
PORT=3001 in .envAGENT_PORT=3002 in .envfrontend/vite.config.jsnpm startnpm start waits on http://localhost:3001/api/health before launching Vite. If the backend failed, the frontend will never start. Check the backend output for the underlying error (most commonly a missing JWT_SECRET, a DB connection failure, or a port conflict).
ER_ACCESS_DENIED_ERROR / cannot connectDB_HOST, DB_PORT, DB_USER, DB_PASSWORD in .envmysql -h <host> -u <user> -p127.0.0.1 only, the dashboard and MySQL must be on the same machineUnknown database 'acore_dashboard'The dashboard database has not been created. Either run the SQL file once:
mysql -u root -p < sql/acore_dashboard.sql
Or grant your configured DB user CREATE DATABASE privilege and restart the backend — it will auto-create the schema.
audit_logs / active_sessions tables missingThese are created automatically on first startup. If they are missing, the user likely lacks CREATE TABLE on acore_dashboard. Run sql/acore_dashboard.sql as a privileged user.
acore_dashboard.audit_logsLogin is capped at 10 attempts per 15 minutes per IP. Wait or reach from a different IP.
You are signed in at GM level 0 or 1. Most server-management pages require GM level 2 or 3. Grant yourself Administrator:
INSERT INTO account_access (id, gmlevel, RealmID)
SELECT id, 3, -1 FROM account WHERE username = 'YOUR_ACCOUNT';
Then log out and log back in. See Access Levels.
The idle timeout is controlled by IDLE_TIMEOUT_MINUTES in .env. Set it to 0 (or remove the line) to disable the timeout, or raise the value. The JWT itself expires after 8 hours regardless.
The server agent process (backend/serverAgent.js) is not running or the backend cannot reach it.
[server-agent] process in your terminal, or start it with npm run start:server-agentAGENT_PORT and AGENT_SECRET match between the backend and the agent (both read from the same .env)npm run start:backendVerify WORLDSERVER_PATH in .env (or path in worldservers.json) points to the actual worldserver.exe/worldserver binary. The working directory defaults to the exe’s directory but can be overridden with WORLDSERVER_DIR / the dir field in worldservers.json.
worldservers.json must be in the project root (same folder as package.json)idSet CONFIG_PATH in .env to the folder containing your module .conf files. Without it, the editor only reads the two main files from the server’s exe directory.
You have not set DBC_PATH. Point it at your WotLK 3.3.5a client’s DBFilesClient folder to enable human-readable names:
DBC_PATH=C:\World of Warcraft\Data\enUS\DBFilesClient
Restart the backend after setting it. See Configuration → DBC Files for the full list of files used.
WoWHead’s tooltip script is loaded asynchronously from an external CDN. If you see item names but no hover tooltips, check your browser’s network tab for a blocked request to wowhead.com — common causes are ad-blockers or offline use.
mysqldump: command not found on backupmysqldump is not on your system PATH. Either add it to PATH or set MYSQLDUMP_PATH in .env:
MYSQLDUMP_PATH=C:\Program Files\MySQL\MySQL Server 8.0\bin\mysqldump.exe
Set MYSQL_PATH the same way if the Restore button fails for the same reason.
The mysql client binary is required for restores — it is separate from mysqldump. Set MYSQL_PATH if needed (see above).
localhost — e.g. http://192.168.1.100:5173ALLOWED_IPS is set in .env, add the client IP to the list, or remove ALLOWED_IPS entirely to accept all private/LAN IPs (the default)Add the origin to FRONTEND_URL (comma-separated) in .env:
FRONTEND_URL=https://dashboard.example.com,http://my-other-host:5173
Private/LAN origins are always accepted regardless of this setting.
[auth], [db], [agent] to narrow down the source