Troubleshoot
The process will not start
Section titled “The process will not start”Pitot validates its whole configuration before opening any listener, so a configuration refusal names the setting. Other startup errors can report storage, listener, or identity-provider failures; read the error before changing settings.
Unknown PITOT_ setting names fail startup, except platform-injected service
discovery names. Check spelling against the configuration reference.
An unresolved compaction blocks startup
Section titled “An unresolved compaction blocks startup”One startup refusal is not about configuration. If a compaction was interrupted
and Pitot can neither finish nor undo it, recovery fails closed and the error
names telemetry/COMPACTION.json.
The marker identifies the authoritative batch set during a swap. The replacement
is staged under telemetry/compaction/ or published as
telemetry/parquet/batches/<output id>.batch. A published replacement lists
its inputs in replaces.json, and its presence alone retires them: inputs keep
their <id>.batch directories until no reader can still open them, and startup
deletes any that remain. Releases before deferred deletion named retired inputs
<id>.retired-<output id>. A completed publish can already have deleted some
inputs; verify every input before attempting a rollback.
Clear the underlying cause, such as a full disk, and start Pitot again. Recovery runs automatically at startup.
If recovery keeps failing, roll the compaction back by hand. With the process
stopped, use telemetry/parquet/batches/ as the batch directory:
- Read
telemetry/COMPACTION.json. It is JSON, with anoutputobject and aninputslist of batch ids. - Back up
telemetry/, then check every id ininputs. Each must exist in exactly one form:<id>.batchor<id>.retired-<output id>. If an id exists in both forms or neither form, stop here. Both forms make the authoritative copy ambiguous; neither means its rows may survive only inside the replacement. Reconcile the batch from the backup, or complete the compaction instead of rolling it back. - Rename each
<id>.retired-<output id>back to<id>.batch. - Delete
telemetry/compaction/<output id>if it exists. - Delete
telemetry/parquet/batches/<output id>.batchif it exists. While it exists itsreplaces.jsonretires the inputs, and startup deletes them; a corrupt replacement continues to block startup. - Delete
telemetry/COMPACTION.json. - Start Pitot.
An unreadable telemetry batch blocks startup
Section titled “An unreadable telemetry batch blocks startup”Pitot also refuses to start when an authoritative .batch directory has
invalid metadata, a corrupt Parquet file, a missing signal file, or a damaged
trace index. First stop Pitot and back up telemetry/, then verify the full
authoritative set:
# Use the same environment and data directory as the server.pitot repair verifyThe command is read-only and reports confirmed corrupt batches. It verifies
batches concurrently, one two-thread engine with a fixed memory limit per two
CPUs; GOMAXPROCS bounds both. Unsupported formats and operational errors
stop verification; they do not authorize quarantine. Restore each reported
corrupt batch from backup when possible. If one cannot be recovered and
discarding only its telemetry is preferable to leaving the instance offline,
set it aside explicitly:
pitot repair quarantine --batch <id>Quarantine is an atomic rename beside the authoritative batch set, not a
deletion. It refuses a batch that validates successfully and refuses any input
or output protected by a live compaction marker. Preserve the reported
quarantine directory for later recovery, run repair verify again, and only
then restart Pitot.
An exporter is rejected
Section titled “An exporter is rejected”Work down this list in order:
- Has setup finished? Before the first administrator exists there is no ingest token to check against, and ingest rejects everything. A collector started ahead of setup fails until you complete it.
- Were all tokens revoked? When no token is active, every exporter gets
invalid ingest tokenover gRPC or 401 over HTTP, the same answer as a wrong token, and the server logs nothing for it. Open/settings/ingeston your Pitot instance. If the list is empty, create a token and update the Collector. - Is it the right credential, in the right header? An active ingest token is
foi_-prefixed and goes inAuthorization: Bearer. Browser sessions and MCP tokens are not ingest credentials. - Is the listener reachable? Both OTLP transports use
PITOT_ADDR(127.0.0.1:7520by default; the image sets:7520). Check container port mappings, bind address and firewall rules. - Right protocol? Both use port
7520. gRPC requires HTTP/2 through any proxy. Usegrpcorhttp/protobufconsistently with the exporter configuration; HTTP/1.1 proxy forwarding cannot carry gRPC.
For OTLP/HTTP, set the exporter protocol to http/protobuf and give it the base
endpoint, http://pitot:7520. Exporters derive /v1/traces, /v1/metrics
and /v1/logs from it themselves.
The raw token is shown once when it is created. If it is lost, an administrator
creates a new one at /settings/ingest on your Pitot instance, or under
Connect telemetry in the account menu, and updates the Collector. A token
that was revoked is rejected on the next request.
HTTP 415: unsupported media type
Section titled “HTTP 415: unsupported media type”OTLP/HTTP requires Content-Type: application/x-protobuf; JSON returns 415.
JavaScript *-otlp-http packages send JSON. Use the *-otlp-proto packages,
such as @opentelemetry/exporter-trace-otlp-proto, or a gRPC exporter in Node.js.
See Common SDKs for language setup.
HTTP 429 or gRPC RESOURCE_EXHAUSTED
Section titled “HTTP 429 or gRPC RESOURCE_EXHAUSTED”Pitot throttles whole exports under ingest pressure. Enable exporter retries
and honor HTTP Retry-After or gRPC RetryInfo. Check disk space, compaction
backlog and query pressure. See ingest admission
for thresholds and metrics.
Someone cannot sign in and SMTP is not configured
Section titled “Someone cannot sign in and SMTP is not configured”SMTP is optional. Creating a local user without it succeeds and reports
invite_delivery: "not_configured" with login_link_required: true. An
operator with shell access to the same configuration and data directory then
mints a link directly:
# For Docker:The link expires after 15 minutes, works once, and is recorded in the
authentication audit history. It is available in local auth mode only; OIDC
installations use
--break-glass.
A configured SMTP relay that fails delivery returns an error. See account recovery for invitation responses and account recovery.
Telemetry arrives but queries look empty
Section titled “Telemetry arrives but queries look empty”Check the namespace. Pitot reads service.namespace from the OTLP resource and
falls back to PITOT_DEFAULT_NAMESPACE, so telemetry exported without one
lands in default.
An unscoped query spans every namespace, so this is only a problem when
something has scoped the query, through a dashboard filter or an MCP call passing
namespace. Clear the scope before concluding the data is missing.
The alert engine and overview read analytical rollups, which follow durable publication. Raw queries can see committed rows before the next rollup pass. See rollup timing.
What to watch in production
Section titled “What to watch in production”The endpoint reference lists health probes, scrape credentials and signals to monitor.