Troubleshooting
Ordered by how often it comes up
Edit this pageOrdered roughly by how often each one comes up.
Installation
docker compose up exits immediately with a variable error
A value marked REQUIRED in .env is blank. The message names it. The
compose file uses the ${VAR:?} form deliberately, so a half-configured
install refuses to start rather than coming up looking healthy.
The database refuses the connection string
POSTGRES_PASSWORD was generated with openssl rand -base64, which produces
/ and + about half the time. That value ends up inside DATABASE_URL,
where those characters make an invalid URL the driver rejects outright. Use
openssl rand -hex 24.
Migrations fail partway
Each migration file executes as one multi-statement query, which PostgreSQL wraps in an implicit transaction — so a failing migration rolls back whole rather than leaving half a schema. Fix the cause and re-run; the runner skips what already applied.
Sign-in
Sign-in redirects to the wrong address
BETTER_AUTH_URL does not match the URL in the browser. It must include the
scheme and the port. This is the single most common issue after putting a
reverse proxy in front — see TLS and reverse
proxy.
The SSO callback returns "invalid state"
The state cookie did not come back. Usually a proxy stripping cookies, or a
redirect URI on a different host from the one that started the flow. The
cookie is scoped to /api/sso and is single-use.
A user deactivated in the directory can still sign in
They were deactivated in the provider but not in Loomscope. OIDC only tells you about people at the moment they authenticate; closing that gap is what SCIM is for.
Magic-link sign-in fails
There is no mail transport in the product, so requesting a link fails rather
than silently succeeding. LOOMSCOPE_MAGIC_LINK_ECHO=true prints the link to
the log — development only, since it writes a single-use credential to
stdout.
Daemons
The daemon exits immediately
LOOMSCOPE_DAEMON_API_KEY is unset. A scanner that starts without
credentials and never scans is worse than one that refuses to start.
The daemon will not register
In order: is the key set and correct; can the daemon reach
LOOMSCOPE_SERVER_URL from inside its network namespace; does the control
plane log show a 401. A 401 means the key is wrong or the daemon was deleted
in the UI — re-enrol it.
The daemon connects, then nothing is scanned
A network must exist in the UI before anything is probed. Then check the
daemon is online, and that the job worker is running — the scheduler is
what enqueues scans.
Hosts appear and then disappear
Two daemons registered under the same name. Each LOOMSCOPE_DAEMON_NAME must
be distinct.
The long poll reconnects every 30 seconds
A proxy read timeout below 60 seconds. The daemon holds
/api/v1/daemon/jobs/poll open for up to a minute.
Discovery
Hosts are not being discovered
In order:
- Does a network exist? Nothing is scanned until one does.
- Is the daemon
onlinewith a recent heartbeat? - Is it falling back to TCP?
docker logs loomscope-daemon | grep "falling back to TCP"— if so, the sweep is probing only 80, 443 and 22. - Layer-2 reachability. ARP needs adjacency.
- A firewall dropping ICMP and the TCP probes.
A host that answers nothing at all will not be found by active scanning. That is what SNMP, ARP tables and flow data are for.
Some hosts are found, most are not
Almost always the ICMP fallback. See above.
Scans queue but never run
No daemon is polling, or the worker is not running. Check Settings → Daemons and Settings → Jobs.
A session is stalled
The daemon stopped reporting progress mid-scan — usually the process died or lost its route. Nothing is lost; the next scheduled run picks the range back up. A daemon that stalls repeatedly is worth investigating.
Data quality
Services are detected but not identified
No signature matches. Write one — see Service signatures — and confirm it loaded by checking the custom signature count on the daemon list.
Vulnerability findings look wrong
Check the matched via column. banner is a heuristic and is where false
positives concentrate: a distribution build with the fix backported still
reports the upstream version, and nothing observable from the network can
tell. Mark it a false positive; that is useful work rather than a workaround.
The vulnerability list looks suspiciously short
Check the feed age. A stale CVE mirror produces a short list rather than an error. In an air-gapped install the mirror is only as fresh as the last copy in.
The application topology shows no real edges
No flow data. Without it, Loomscope draws lighter co_hosted placeholder
edges rather than an empty graph. Point your switches and routers at the
daemon's NetFlow listeners — UDP 2055 and 6343 by default.
The L2 topology has no adjacencies
No SNMP credentials for the switches. LLDP and CDP neighbour tables are the only source for those edges.
Operations
Stored credentials fail to decrypt
LOOMSCOPE_KMS_KEY differs from the one in use when they were written.
Restore the original; there is no recovery path without it. This is the
failure mode that looks healthy — see Backup and
restore.
Snapshots stopped
The scheduler is not running. Check Settings → Jobs for the last run of
inventory.snapshot, and check the worker container is up. The 60-day
density strip on History shows the gap.
Scheduled work stopped after a restart
A failed tick is retried within a run but not across a restart — a worker that died mid-retry resumes the normal schedule. Confirm the worker is running and that the next natural tick landed.
Realtime updates stopped
SSE is being buffered by a proxy. Turn response buffering off for
/api/sse — see TLS and reverse proxy.
Everything is slow
Check PostgreSQL connections first. Exhaustion presents as slowness rather than as an error:
SELECT count(*) FROM pg_stat_activity WHERE datname = current_database();Then check disk. Snapshots and audit entries accumulate with no automatic pruning.
Getting help
Include, in this order: the version, the deployment shape (Compose, Helm,
systemd), what you expected, what happened, and the relevant log lines with
LOG_LEVEL=debug. Redact nothing — the logger already redacts credentials,
API keys, community strings and session tokens.
Open an issue. Vulnerabilities go to the private channel in SECURITY.md instead.