Troubleshooting
You integrated an SDK, ran your game, and no data appears. Work through the checks below in order.
How fresh is fresh?
Section titled “How fresh is fresh?”Once the pipeline is warm, an ingested event is queryable within seconds. The first event after an idle period can take longer because the storage backend resumes from cold, so wait a couple of minutes before concluding that delivery failed. If nothing has arrived after a few minutes, move on to the transport checks.
Enable verbose logging
Section titled “Enable verbose logging”By default the SDK logs little about delivery, so turn on verbose logging first. It tells you whether a batch left the process and what the server returned.
- Unity: set
TelemetrySDK.Instance.VerboseLogging = true;(before or afterInitialize). A successful flush logs[Framedash] Flushed N events (HTTP 202). - UE5: the SDK logs under the
LogFramedashcategory. Launch with-LogCmds="LogFramedash Verbose"(or runLog LogFramedash Verbosein the console). A send logsSendBatch: N events -> ...followed by the HTTP result. - Godot: set
TelemetrySDK.Instance.VerboseLogging = true;(before or afterInitialize). A failed transport logs the retry ladder, e.g.[Framedash] Retry 1/3 in 1.0s (HTTP 0).
Read the result code
Section titled “Read the result code”The logged HTTP status tells you where the problem is:
- 202 — accepted for asynchronous processing. The request reached the ingest queue, but this is not durable-storage confirmation: downstream validation can still discard an invalid event. Verify a unique marker as described below.
- 0 (Godot) or a connection timeout — a transport-level failure (DNS, TLS, proxy, or IPv6), not an API rejection. See the next section.
- 401 / 403 — the API key is missing or lacks the
events:writescope. Use an Ingest preset key. - 415 — wrong
Content-Type. Only relevant to custom senders; the ingest endpoint accepts protobuf only. The official SDKs set this for you.
Transport-level failures
Section titled “Transport-level failures”A status of 0 or a repeated connection timeout means the request never reached the server. Confirm the endpoint is healthy from the same machine, then isolate the cause:
curl -4 -sv https://ingest.framedash.dev/v1/eventscurl -6 -sv https://ingest.framedash.dev/v1/eventsA healthy host answers over IPv4 in well under a second (a bare request returns a 4xx structured error, which still proves reachability).
- Broken IPv6: the SDK prefers IPv4 and falls back to IPv6, but on a host whose IPv6 egress is broken you may still see a short series of connection timeouts before data flows. If
curl -4succeeds whilecurl -6hangs, disable IPv6 on the affected interface, or add an IPv4hostsentry foringest.framedash.dev. - DNS quirks: Godot’s
HttpRequestuses its own asynchronous DNS resolver, which can fail (HTTP 0) even when the OS resolver andcurlsucceed. A flaky or split-horizon DNS path is the usual cause. - Proxies: a corporate proxy or firewall may block the ingest host. If
curltohttps://ingest.framedash.devfails from the same machine, fix the network path before looking at the SDK.
The offline queue
Section titled “The offline queue”Unity and UE5 persist unsent events to an on-disk queue on a graceful shutdown or a transient send failure, and flush them on the next initialization once the game loop ticks. The queue is not written on a hard kill (for example a CI timeout kill), so anything still buffered at that point is lost. A short headless run that shuts down gracefully can therefore look like it “sent nothing” while the events wait in the queue — this is expected: run the game again (or keep it running longer) and the queued batches flush. In CI, wait for the HTTP 2xx line in the log before killing the process rather than relying on the queue. See the per-engine headless guides (Unity, UE5) for the details.
Godot has no on-disk queue. In Godot SDK 0.1.5 and later, Shutdown() drains the buffer synchronously through a blocking send bounded by a 2.5s budget. There is still no offline queue, so a send that fails within that budget, or a process force-killed before the drain finishes, loses the unsent events. See the Godot headless guide.
Unity: “Package Manager Cancelled resolving packages” in batch mode
Section titled “Unity: “Package Manager Cancelled resolving packages” in batch mode”A Unity batch-mode run can fail with Package Manager Cancelled resolving packages right after you add the git package. The cause is a stale Temp/UnityLockfile left over from project creation. Close the editor, delete Temp/UnityLockfile, and retry.
Verify arrival
Section titled “Verify arrival”To verify an exact marker without the dashboard, run raw SQL with a Full key carrying the data:admin scope. A Read-only key’s analytics:read scope can access aggregate analytics APIs but cannot run framedash query; an Ingest key’s events:write scope has no read access. When testing a custom sender, replace <unique-id> in ingest_probe_<unique-id> with a UUID or similar value for each run. Reusing a marker can make an older event look like a successful current run.
# Which project does this key belong to, and is it valid?framedash auth --api-key-file read.key
# Did this run's unique marker reach durable storage? (Full preset key, data:admin scope)framedash query --api-key-file full.key --project-id <id-from-the-auth-command-above> \ "SELECT count(), max(timestamp) FROM events WHERE event_name = 'ingest_probe_<unique-id>'"An Ingest (events:write) key cannot enumerate its own project, so “which project am I writing to?” is not answerable from the ingest key itself. Check the dashboard, or create a Read-only key in the same project. See the Events Schema for the columns you can select.
Next Steps
Section titled “Next Steps”- Events Schema: columns and query rules
- CLI Reference:
framedash authandframedash query - Quick Start: the integration flow