---
url: https://simpledatalogs.com/docs/reference/troubleshooting.md
description: >-
  Fix common problems by the answer you get from ingest, and by what you see, or
  don't see, on the dashboard.
---

# Troubleshooting

Start with the answer your request got. Every SDK logs it: `console.warn` in JavaScript, `os.Logger` (subsystem `com.simpledatalogs.sdk`) in Swift, and PHP's error log in Laravel. With curl, add `-i` to see the status.

## By response

### `401 invalid_key`

The key is unknown, revoked, or brand new.

* **Just created it?** A new key goes live within a few seconds. Wait and retry; our SDKs re-probe on their own.
* **Copied it whole?** Keys start with `sdl_pub_` or `sdl_sec_`. Check for a cut-off end or a stray quote.
* **Right header?** `Authorization: Bearer sdl_…` on `/v1/ingest`. Drop-ins put the key where their protocol does: the DSN for Sentry, `DD-API-KEY` for Datadog, `Authorization: Splunk …` for HEC.
* **Revoked?** The **Keys** tab lists only active keys. Compare the key's prefix with the list; a revoked key is gone from it.

### `413 payload_too_large`

The body was over 512 KB as sent. Send smaller batches, turn on gzip, and aim for 256 KB per request. Our SDKs split and resend on their own.

### `415`

* `unsupported_content_encoding`: use gzip, or no compression. Brotli, zstd and deflate are refused. sentry-python picks brotli when the `brotli` package is installed; see [Sentry](/integrations/sentry#tips).
* `unsupported_content_type`: a drop-in path got a Content-Type it doesn't take. Segment paths need `application/json`; OTLP needs `application/x-protobuf` or `application/json`.

### `429 rate_limited`

One key sent over 200 requests a second. Batch more per request, or give busy sources their own keys. Honor `Retry-After`.

### `429 over_quota`

Your organization sent twice its monthly quota. Data waits in your senders' outboxes; upgrade on the **Billing** page, or wait for the next month. See [Plans and limits](/reference/limits#past-your-quota).

### `503 busy`

Ingest is overloaded or storage is briefly unavailable. Retry after `Retry-After`. Nothing is lost while your client keeps its outbox. [status.simpledatalogs.com](https://status.simpledatalogs.com) shows whether an incident is open.

### `404` on `/v1/traces` or `/v1/metrics`

Only OpenTelemetry **logs** are stored. Set `OTEL_TRACES_EXPORTER=none` and `OTEL_METRICS_EXPORTER=none`, or use the Collector's `logs_endpoint`.

### A timeout or a connection reset

Unknown whether it was stored, so retry; `event_id` makes a copy harmless. Resets often mean a body far past 512 KB, which ingest refuses by closing the connection.

## By symptom

### I got `202`, but nothing shows up

1. **Right environment?** The key decides the environment and the deployment. Open the **Keys** tab of the environment you're looking at and check the key's prefix.
2. **Right deployment tab?** With several deployments, check the **All** tab.
3. **Check Unparsed.** A body that couldn't be read is there, with a reason. See [the reasons](/api/templates#the-unparsed-tab).
4. **Old `ts`?** An event is counted on the day of its `ts`, not the day it arrived. An app that sends a backlog after days offline fills past days.
5. **Over quota?** Between 100 % and 200 % of the quota, events are stored but hidden, with a banner.

### Counts are higher than expected

* **Retries without ids.** Events without `event_id` and `ts`, and all text lines, count again when a request is retried. Send NDJSON with both.
* **`ts` set at send time.** If you stamp `ts` when sending rather than when tracking, each retry gets a new time and can't be deduplicated.
* **Two senders.** An app and its server tracking the same action count it twice. Pick one.

### Active devices are zero

No identity field arrived. Send a `device_id` (or `install_id`, `anonymous_id`, `user_id`, `session_id`) with each event, or call `setDeviceId` / `setDeviceID` in the SDK.

### A log line has no level

The level wasn't one of the six, or a common spelling of one. The original value is kept as `props.level`. Map it in your logger, or set a [text template](/api/templates).

### My stack trace is split into several rows

Only lines that look like stack-trace lines join the entry before them: indented lines, `at …`, `#0 …`, `Caused by…`. Make sure your logger indents trace lines, and send each trace in one request. See [Stack traces](/api/log-lines#stack-traces).

### A browser request fails with a CORS error

Ingest answers every origin, so a CORS error usually hides another failure. Check the network tab for the real status, and make sure the page sends to `https://edge.simpledatalogs.com/v1/ingest` with a public key.

### The MCP server answers `401`

The token was revoked or mistyped, or the chat app's connection was disconnected. Create a new token, or reconnect the app. See [MCP: when something goes wrong](/mcp/clients#when-something-goes-wrong).

## Still stuck?

First check [status.simpledatalogs.com](https://status.simpledatalogs.com). It probes the dashboard, ingest in each region and these docs every 5 minutes, and lists open incidents. It runs apart from our servers, so it stays up when they don't.

Then send the request with `curl -i`, and keep the `accepted` id or the error body. They tell us exactly what happened to it.

## Next steps

* [Responses](/api/responses): the full table.
* [Writing a sender](/api/sender-rules): the rules that prevent most of these.
