Troubleshooting
Check one hop at a time: is the server running, can the browser reach it, can the agent reach it, can the agent reach the network it scans. Change one thing, then test again.
Each entry below starts with what you see, then the likely cause and the fix.
Where the logs are
Start with the log. MiniPAM writes to several places:
- Console. The server prints INFO lines to standard output and WARNING and above to standard error. With
systemd, read them with
journalctl. - Docker.
docker logs minipam, ordocker logs -f minipamto follow. - Log files, if you turn them on with
files.enabled. MiniPAM writes one file per stream infiles.directory:api.log,agent.log, andbackground.log. Each line is JSON. - Administration → System → Logs (admins). The recent log of the running server, kept in memory, with filters for stream, level, module, and text. It keeps DEBUG lines even when the console is at INFO. It is cleared when the server restarts. See Logs.
On the Logs page, the System button changes logging without a restart:
- Temporary levels raise or lower the level of one module (a logger name prefix, or
*for all) for 5 minutes, 15 minutes, or 1 hour. They change the console and the log files, not the in-memory view. - Temporary exclusions hide noisy lines everywhere, including the Logs page, for up to 24 hours.
Both expire by themselves, and a restart clears them. To keep a level, set
module-levels in the configuration file.
To diagnose a problem:
- Agent or job problems: the full messages exchanged with agents (
agent_request_outbound,agent_response_inbound) are logged only at DEBUG. The Logs page shows them already. To get them in the console or log files too, setapi.agent.wsandservices.job_runtimeto DEBUG. - Database problems: set
db.sqlto DEBUG. SQL statements are recorded only while it is at DEBUG, also on the Logs page. - Reproduce the problem, then read the first error, not the last one.
The server does not start
Read the first error in its output. Common causes:
- The port is in use. Another process listens on
8091. Stop it, or changelisten.http. frontend-directoryhas noindex.html. Build the interface first, or remove the setting.- The configuration file is missing. A file given with
--configorMINIPAM_CONFIGmust exist. - The database migration failed. MiniPAM restored the safety copy and stopped. See If an upgrade fails.
- Two versions share one database. Stop every other server that uses the same file.
curl http://localhost:8091/health returns {"status":"ok"} once the server is up.
Database errors at startup
Any startup failure ends with Application startup failed while applying database migrations, followed by the
configuration and database paths. That line is the same for every cause. Scroll up to the first error above
it:
This is a non-empty database without an Alembic revision.The file comes from a pre-alpha MiniPAM, which has no upgrade path. Start the old version, export your inventory with Data transfer, then start the new version with a fresh database and import the file.Database revision '…' is not supported by this MiniPAM build.The database was migrated by a newer MiniPAM. You cannot go back to an older version on it. Run the newer version again, or restore a backup made before the upgrade. See Upgrades and backups.Timed out waiting for another MiniPAM process to finish database migration work. Another MiniPAM process holds the migration lock (database.db.migration.lock, next to the database). Stop the other server or CLI command, then start again.Fresh database initialization at '…' failed.Creating a new database failed half-way. Delete the incomplete database file named in the message and start again.Database migration from … to … failed.MiniPAM restored the safety copy. See If an upgrade fails.
Inventory looks empty after a restart or upgrade
You sign in and see no sites or devices, or the Create initial admin form appears again.
Cause: the server opened a different, new database. Usually one of these:
- The Docker data volume is not mounted, or a different one is: check
-v minipam-data:/var/lib/minipam. server.database.locationchanged. A relative path is resolved from the folder that holds the configuration file, so moving that file moves the database too.- The server started with a different configuration file.
Fix: find out which file the server opens: Administration → System → Database usage shows its path,
and so does cli.py db usage. Point the configuration or the volume back at your real database and restart.
Do not create a new admin on the empty database first.
The page loads, but nothing works
Open the browser's developer tools, go to the Network tab, and look at one failing request.
- Requests go to port
8000. The interface was built withoutVITE_API_BASE_URL. Rebuild it withVITE_API_BASE_URL=/ npm run build. See Install from source. - Requests fail with a CORS error. MiniPAM has no CORS support. Serve the interface and the API from the
same address, either with
frontend-directoryor through one reverse proxy. - Saving anything fails with
E2403"The CSRF token is missing or invalid". Reading works, but every change is refused. The browser did not send the CSRF cookie that matches the page's token. Reload the page first: signing in again in another tab replaces the token. If it keeps happening behind a proxy, make sure the proxy passesCookieandSet-Cookieheaders unchanged, and that you open MiniPAM with the same scheme the server thinks it uses. Withtrust-proxy-headers: trueandX-Forwarded-Proto: https, cookies are marked Secure, and a browser on plainhttp://does not send them back. - You are signed out straight after signing in, behind HTTPS. You set
cookie-samesite: none. Browsers reject such cookies unless they are marked Secure. Settrust-proxy-headers: trueand make sure the proxy sendsX-Forwarded-Proto: https, or go back to the defaultlax.
The error codes are listed in API errors.
There is no "Create initial admin" form
The form only appears when no admin exists and
bootstrap-token is set. Set the token and restart the server,
or create the admin from the command line with cli.py auth set-root.
If an admin already exists, the form does not come back, even with a bootstrap token set. The token is single-use. To regain access, reset the admin password. See Create the first admin.
If the form shows up although you already had an admin, the server opened another database. See Inventory looks empty after a restart or upgrade.
Forgotten admin password
Reset it with cli.py auth set-root --loginname <name>. See
Reset the admin password.
An agent stays offline
On the agent's machine, check the log: journalctl -u minipam-agent -f, or the terminal if you run it by
hand.
- Wrong or missing token. The log shows
status_code=403, then the agent exits withfailed to connect upstream service. The server refuses the connection before it opens, and logs nothing about it. The token must match the agent's token exactly (choose Reveal on it in Administration → Agents). As a service, the agent restarts every 5 seconds and fails the same way until you fixMINIPAM_KEYin/etc/minipam/agent.env. - Wrong address. It must end in
/ws/agent, for examplews://minipam.lan:8091/ws/agent. The built-in default is out of date, so always pass--address. - The server is down when the agent starts. The first connection is not retried: the agent exits, and the service restarts it every 5 seconds until the server answers.
- Wrong site. The agent appears under the site it was created in. Check the Active site selector.
- A proxy in between. It must allow WebSocket upgrades and long-lived connections. Use
wss://when the proxy serves HTTPS. - DNS or certificates. From the agent's machine,
curl https://minipam.example.com/healthshould work.
An agent that connects but is missing a module, such as nmap enrichment, has it disabled or lacks what it
needs (nmap, root). See What an agent can do.
An agent stopped reconnecting
The agent was online, the server or network was down for a long time, and the agent never came back.
Cause: after a lost connection, the agent retries 100 times. It waits 3 s, 5 s, 9 s, 20 s, 37 s, 1 min,
and 2 min, then starts the cycle again, so it gives up after about an hour. It keeps running, and logs
failed to reconnect upstream from ping loop every 5 seconds, so systemd does not restart it.
Fix: restart it: sudo systemctl restart minipam-agent.
Two agents keep replacing each other
One agent flips between machines, or jobs on it hang.
Cause: two machines use the same token. Each new connection replaces the previous one. Work goes to the newest connection only, and results for requests sent to the other one are dropped.
Fix: create one agent, with its own token, per machine.
A job fails or never finishes
Open the job under Discovery → Jobs and read its first error. See Read a failed job.
Agent 'N' is not currently online.(statusstart_fail). The job was never sent. MiniPAM does not queue work for offline agents. Bring the agent online, then run the job again.The agent disconnected before the job completed.(statusexpired). The connection dropped mid-job. Jobs are not resumed. Run it again.Failed to process agent message: …The server could not read a message from the agent. Usually the agent and server are different versions. Update the agent to match the server.The server could not persist the validated agent result.The message was valid, but saving it failed. Look foragent_message_storage_failedin the server log, and for database errors around it.- The job stays
runningafter a server restart. The server does not expire jobs that were running when it stopped. Run the job again.
A scan fails or finds little
Open the job under Discovery → Jobs and read its first error.
- ARP netscan needs a directly attached network, not a NAT network (see
Where to run an agent), and the
cap_net_rawandcap_net_admincapabilities, or root. Trysudo minipam-agent run arp-scan --liston the agent's machine. - Port probes and nmap enrichment need
nmapon the agent's machine. UDP port probes need root. OS detection also needs root andallow-privileged-detail: true. - A script was refused. It is not in the agent's
allowed-scripts. - Ping fails with a permission error. Allow unprivileged ping with
sudo sysctl -w net.ipv4.ping_group_range="0 2147483647".
A scan that completes can still have thin evidence. Fix the cause, then use Scan now or Retry scan in the review queue instead of accepting a weak suggestion.
Nothing reaches the review queue
A netscan finished, but the review queue stays empty or fills slowly.
Cause: netscan evidence is processed in the background, not straight away:
- Schedules start 30 seconds after the server starts.
system.discovery.process_dirtyruns every 60 seconds and handles up to 100 devices per run. A netscan that found 500 devices takes about 5 minutes to reach the queue.- A device is processed again only when its evidence changed. A scan that finds the same thing adds nothing.
- Runs missed while the server was down, or while it was starting, are skipped, not caught up.
Device scan (nmap enrichment) results are processed as soon as the scan finishes.
Fix: wait a few minutes, and check that the system.discovery.process_dirty schedule is not paused under
Discovery → Jobs → Schedules. See
How the pipeline runs.
Devices wait in a device scan
When you choose Preview device introspection under Discovery → Device Scans, some devices are listed under Waiting devices, each with the reason:
No current IP address is known.Run a netscan that sees the device.The current IP address has ambiguous active network scope.The address is in more than one network. Fix the overlapping networks.Waiting for a capable online agent with a route to this address.Bring an agent online that reaches the address and has nmap enrichment enabled.This agent does not support the … profile.Choose another depth, or update the agent.This agent cannot run the privileged Deep profile.Use Standard, or turn onallow-privileged-detailon the agent.Waiting for scan capacity on this agent.Wait for running scans to finish, or raise the concurrency under Scheduling policy.Introspection is excluded for this device.,This device is outside the networks selected for introspection., orThe current address is in an excluded network.The site's introspection policy leaves the device out. These lists have no page yet; admins read and change them through/v1/api/discovery/introspection/policy?site_id=….
A template is Blocked or Unprotected
- Blocked: a
requirefailed. Open the template's Checks tab, read the failing message, fix the inventory or the requirement, and choose Run checks. The last approved output keeps being served in the meantime. - Unprotected: nothing guards the template. It still works, but automatic publication needs at least one
requireor linked check. - A render fails with a limit error. The template queried or produced too much. See Limits.
A template render or download fails
Template rendering exceeded the 3-second safety limit.A render may take 3 seconds at most. Narrow the queries, and move repeated lookups out of loops.The template renderer is busy. Try again in a moment.At most two renders run at once. Wait and retry.E1404"This template has no approved output." Nothing is published yet. A cron job that fetches…/outputs/downloadgets this until you approve the first output. See Templates.- "Withdraw the approved output before deleting…" You cannot delete an approved output, or a template that has one. Choose Withdraw on the output first.
The database is locked
The log or an error message shows database is locked.
Cause: another process held a long write on the database. MiniPAM runs SQLite in WAL mode, so reading never blocks, but only one writer works at a time. A writer waits up to 5 seconds for the lock, then fails. Routine writes take milliseconds, so a longer wait usually means one of these:
cli.py db vacuumis running. It blocks writers until it finishes.- A large Data transfer import is running.
- A second MiniPAM server, or another tool, writes to the same
database.db. - The database is on a network share (NFS, SMB), where SQLite's file locking does not work reliably.
Fix: wait for the vacuum or import to finish and retry. Run db vacuum with the server stopped. Stop any
other server or tool that opens the same file. Move the database to a local disk or Docker volume, set
server.database.location, and keep database.db-wal and
database.db-shm with it: move all three with the server stopped.
The database keeps growing
Look at Administration → System → Database usage, or run cli.py db usage, to see which tables grow. Then
lower the matching retention setting under System → Settings: jobs and job logs, discovery activity,
template revisions, or template outputs.
Deleted rows leave free space that SQLite reuses, so the file does not shrink by itself. To give that space back to the disk, see Compact the database.
Asking for help
Include the MiniPAM version, what you did, what you expected, what happened, the time it happened, any job ID, and the first specific error from the log. Leave out tokens, API keys, cookies, and unredacted exports.