Troubleshooting the server
The Dungeon Master
It narrates fights but never rolls anything
Tool calling is off or unreliable. On llama.cpp, start the server with --jinja. Make sure DM_THINKING=0 is not set: under the long prompt a non-thinking model surfaces tool calls about one turn in five. Keep presence_penalty at 0 in any server-side preset. With a remote key, confirm the model supports function calling. Run Test backend in the admin panel: the tool-call step is the one that fails.
It repeats itself or forgets what just happened
A context window that is too small, so the prompt is being truncated. Serve a local model with a 64K window (-c 65536); the server reads the real window from llama.cpp and packs against it. For an unknown OpenAI-compatible endpoint the server assumes 16K unless OPENAI_COMPAT_CONTEXT says otherwise; Known hosted models use catalog context sizes capped at 128K; an OpenAI model absent from the catalog uses a 128K fallback. The Context tab at the table shows what was cut.
Turns take minutes
Expect 1.5 to 3 minutes per full turn on a single local GPU, longer in combat. Beyond that: cap the reasoning budget on the server to about 1024 to 2048 tokens, check that a picture or a narration render is not queued ahead of the turn on the same GPU, and on a 16 GB card serve gpt-oss-20b, which fits on the card whole, rather than a larger model spilling into system memory. While a turn runs the table shows its stage, and the admin's Server log shows where it is.
"Could not reach the backend"
The message says why: the transport's own reason (refused, timed out, no such host), and whether the server is down or answering but listing several models with none chosen. From Docker, use host.docker.internal rather than 127.0.0.1; Ollama addresses keep their own port. A model listing that once reported "Nothing answered" while the server was busy now waits for the reply. Run Test backend after any change.
New campaigns only offer a human Dungeon Master
The server has no text model set up, so the AI, steered and assisted seats are refused, Quick start too, and a running table cannot be handed to the AI. Set a text model (or an agent program) in Admin; a storyteller that is set up but not answering still counts.
The table says "The model is unavailable" now and then
A local model server (llama-server, Ollama) closed an idle connection just as a request arrived on it. Since 0.26.2 the server asks again once on a fresh connection, and since 0.28.4 it also asks again once when llama.cpp throws a reply away. A backend that is down, refuses, or times out still fails, and Ask the DM's log line names what the backend said.
A turn crashed and the table is stuck
The lead can send the turn back in from the Lead tab. It resumes from the persisted conversation, nothing is re-rolled, and no context is lost. The server log names the failed request.
The reasoning model rejects a parameter
The server drops the named field and retries, up to three fields per request. If a strict vendor still refuses, check the model name and that the base URL ends in /v1.
A local model's turns end empty, or a fight ends mid-fight
The prompt ran out of window. The tool definitions use part of each call's window; the budget counts them and scales the reply reserve to the window. Context shows the measured Tool definitions cost, which depends on the tools offered. Serve at least a 64K window, and update a server older than 0.24.9.
Content and characters
Most spells, monsters or subclasses are missing
No content pack. Run node scripts/import-open5e.mjs, or download open5e.sqlite.gz from the release and point CONTENT_DB_PATH at it, then restart. The Docker image and the apps carry the pack already.
Continue is disabled in the builder
A panel still has picks to make; each reads "N still to choose", and the reason sits beside Continue with Show me, which jumps to the missing pick. A rogue or a level 3 or higher bard was blocked at the class step before server 0.21.2; update.
Pictures, narration, ambience
No portraits, scene art or covers
First check pictures are on and a model is selected. Blank OpenAI or ComfyUI model fields mean no pictures. Otherwise the backend may be down, busy or at another address. Placeholders are by design so the session continues. Check the URL in Admin, Images, and from Docker use host.docker.internal rather than 127.0.0.1. On an integrated GPU, a render waits behind the Dungeon Master's turn.
Narration is on but silent
The speech server in Admin, Speech is wrong, switched off, or not running; press Test narration. The passage says why at the table and the server log shows the failed request. Each listener also has a mute and a volume in the voice dock.
Ambience does nothing
The sound library is missing: an install without public/ambience, or an app-hosted world that has not downloaded it yet. Admin, Sound library downloads it, or npm run fetch-ambience -- --pack on a source install.
A map stays on charting after a restart
The current server marks interrupted map renders as failed at startup. Use the Map panel's redraw control or Use the placeholder instead. Update an older server that leaves the render pending indefinitely.
Voice
The microphone button does nothing
Plain http in a browser. Browsers grant the microphone on HTTPS or localhost only. The apps are exempt.
Everyone connects, then silence
With the media server transport: the media port (44444, UDP and TCP) is closed or not forwarded, or the announced address is unset behind NAT or Docker. A Cloudflare-proxied voice domain has the same effect. See Voice chat setup.
Reaching the server
My party cannot reach it on the LAN
Bind to all interfaces (npm run start:lan or dev:lan, or Docker) and allow port 3005 through the host firewall. Players use the host's LAN address, not localhost. The server's own QR button (bottom right of every page) encodes the address for a phone.
Share links point at 127.0.0.1 or a Docker address
Set the Public URL in Admin, Server settings, or APP_PUBLIC_URL. The QR button and invite links are built from it.
The sign-up form asks for a Setup code
The server has no accounts yet. Its log prints the one-time code at every start, with a link that fills it in (under Docker: docker compose logs | grep -A12 "no accounts yet"). The first account cannot use Discord. See First run and accounts.
Sign-ups refused, or "invite-only"
The sign-up mode. Open it, mint an account invite, or let the player in with a live room code. See First run and accounts.
Discord sign-in fails
The redirect URI in the Discord application must be exactly <public-url>/api/auth/discord/callback, and the Public URL must match how players reach the server.
The database
I lost the encryption key
There is no recovery path. Under Docker the key is stored at data/.db-key in the data volume and was printed once on first boot: retrieve it from the volume or the logs before that container is gone. A backup can include it through data/.db-key or .env.server. If it was supplied only through the process environment, recover that original value from your deployment configuration.
"The built-in engine cannot decrypt an encrypted database"
The native SQLite module did not load, so the server fell back to Node's built-in engine, which cannot read an encrypted file. Reinstall dependencies (npm install) on a supported platform, or force the driver with ODM_SQLITE_DRIVER=native to see the real load error.
The container never becomes healthy
docker compose logs. A wrong or changed key is the usual cause; the image is glibc-based on purpose, so an Alpine variant will not run the native modules.
Logs
A host install writes to standard output and logs/; Docker to docker compose logs -f. DM_DEBUG=1 logs every prompt and tool call for a Dungeon Master problem. When you open an issue, include the server version (the account menu's About, which copies the exact build), the backend and model, and the log lines around the failure.