Troubleshooting & FAQ
Startup
Section titled “Startup”The API exits with “Set DATABASE_URL and QUERYPILOT_ENCRYPTION_KEY”
Section titled “The API exits with “Set DATABASE_URL and QUERYPILOT_ENCRYPTION_KEY””Both are required. With Docker Compose, DATABASE_URL is assembled for you; set
QUERYPILOT_ENCRYPTION_KEY in .env (openssl rand -base64 32). The key must decode to 32 bytes
from base64 or hex.
“Invalid environment configuration” or “Invalid QueryPilot configuration”
Section titled ““Invalid environment configuration” or “Invalid QueryPilot configuration””A variable could not be parsed (for example API_PORT=eighty) or a value is out of range. The
message lists every offending setting. Booleans accept true/false, 1/0, yes/no and on/off.
The web app says the API is unreachable
Section titled “The web app says the API is unreachable”NEXT_PUBLIC_API_URL must be the API URL as reachable from your browser, and the web app’s
origin must be listed in QUERYPILOT_CORS_ORIGINS.
Connecting a database
Section titled “Connecting a database”pg_stat_statements shows as MISSING
Section titled “pg_stat_statements shows as MISSING”The extension must be preloaded (requires a restart) and created in the observed database:
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;With the bundled Compose PostgreSQL, the extension is created only when the data volume is first
initialized. An older volume needs the CREATE EXTENSION by hand.
pg_stat_statements is installed but not readable
Section titled “pg_stat_statements is installed but not readable”The role can see that the extension exists but is not allowed to read it. Grant pg_read_all_stats.
Only the monitoring role’s own queries appear
Section titled “Only the monitoring role’s own queries appear”Also pg_read_all_stats: without it, other roles’ statements are hidden.
“Multiple projects exist, so projectId is required.”
Section titled ““Multiple projects exist, so projectId is required.””QueryPilot attaches new databases to the only project when there is exactly one. If several exist,
pass projectId when registering the database through the API.
Agents
Section titled “Agents”The agent is not ready
Section titled “The agent is not ready”Check its readiness endpoint, which states exactly what is wrong:
curl -s http://<agent-host>:8082/health/ready| Check | Value | Fix |
|---|---|---|
configuration |
a list of problems | Set QUERYPILOT_API_URL, QUERYPILOT_AGENT_TOKEN, QUERYPILOT_TARGET_DATABASE_URL. |
database |
unreachable |
Check the connection string, network path and the role’s CONNECT privilege. |
api |
not registered |
The API cannot be reached yet; check QUERYPILOT_API_URL and egress rules. |
api |
token rejected |
The token is wrong, rotated or revoked. Rotate it in the UI and update the agent. |
The agent shows OFFLINE
Section titled “The agent shows OFFLINE”No heartbeat has arrived for three heartbeat intervals (90 seconds by default). The agent process is down, or it can no longer reach the API.
The agent is DEGRADED, or the Agents panel lists collector errors
Section titled “The agent is DEGRADED, or the Agents panel lists collector errors”One or more collectors are failing, usually because of a missing privilege for one system view. The other collectors keep running. Run Test connection on the database for a remediation.
“Waiting for telemetry — start the agent to begin collecting.”
Section titled ““Waiting for telemetry — start the agent to begin collecting.””Nothing has been collected for this database yet. Create and start an agent.
“No executions in this window.”
Section titled ““No executions in this window.””Telemetry exists, but the selected time range contains no executions. Pick a longer range.
Charts have gaps
Section titled “Charts have gaps”A gap means nothing was collected (or nothing executed) in that bucket. QueryPilot deliberately never draws those buckets as zero.
A grey dashed line says “stats reset”
Section titled “A grey dashed line says “stats reset””pg_stat_statements counters were reset (for example by pg_stat_statements_reset() or a server
restart). QueryPilot detects the reset and does not count it as a negative delta.
Why are percentiles marked “est.”?
Section titled “Why are percentiles marked “est.”?”pg_stat_statements does not record individual executions, so p50/p95/p99 are estimated from each
interval’s exact mean and variance. The mean is exact.
Execution plans
Section titled “Execution plans”“Plan capture is not supported for this database”
Section titled ““Plan capture is not supported for this database””Plan capture needs PostgreSQL 16 or newer (for EXPLAIN (GENERIC_PLAN)) and a readable
pg_stat_statements. You can still upload plans.
An on-demand capture failed
Section titled “An on-demand capture failed”The reason is shown on the request. Common ones:
| Message | Meaning |
|---|---|
| Only SELECT statements are planned by the agent. | Capture is limited to single SELECT statements. |
| The text contains more than one statement. | Refused for safety. |
| This is a monitoring query, not application workload. | Queries against statistics views are skipped. |
| No PostgreSQL queryid is recorded for this query yet. | Wait for the next query-stats collection. |
| The query is no longer in pg_stat_statements. | The entry was evicted or reset. |
| canceling statement due to lock timeout | A stronger lock (such as a migration) held a table; the agent gave up after 100 ms rather than queue. |
| permission denied for table … | The monitoring role cannot read a table the query uses. |
A request stays EXPIRED when no agent picks it up in time. Check that an agent is online for the database.
Does QueryPilot write to my database? No. Sessions are read-only at the PostgreSQL level, and plan capture runs in a read-only transaction that is rolled back.
Does it need a superuser? No. pg_read_all_stats plus CONNECT is enough for everything
except planning queries against tables the role cannot read.
Does it run EXPLAIN ANALYZE? Never automatically. You can upload EXPLAIN ANALYZE output you
produced yourself.
How much load does the agent add? Two connections at most, collector queries capped in rows and
time, and default intervals of 5 s to 60 s. The agent measures its own collection time and exposes it
on /metrics.
Which PostgreSQL versions are supported? 12 and newer; plan capture needs 16+.
Does any data leave my infrastructure? No. There is no phone-home telemetry, and every optional integration is off by default.
Is there authentication? Not yet; it is on the roadmap. Deploy on a trusted network.
Does it support MySQL or other databases? No, QueryPilot is PostgreSQL-only.