Errors

Ingest error codes with what to do next: body limits, spike valve, and rate caps.

Ingest and most API failures return JSON:

{ "error": "invalid_dsn", "message": "DSN authentication failed" }

Error response shape

The dashboard session gate returns { "error": "unauthenticated" } with no message. Login and register rate limits return plain text 429.

Ingest error codes

HTTPerrorWhat happenedWhat to do
400invalid_envelopeMalformed envelope, or no event itemUse a fixture from fixtures/sentry/ or an official SDK
400invalid_storeEmpty, invalid JSON, or decompress failureSend JSON or gzip/zlib with Content-Encoding
400invalid_release_versionVersion contains .., /, or \Use a path segment like 1.0.0
400invalid_release_fileMissing file or path escapeMultipart field file; see Source maps
401invalid_dsnMissing/invalid DSN credentialsCopy key from Settings → SDK connection
403dsn_revokedKey revokedCreate or rotate; update dsn
403project_mismatchKey does not belong to {project_id}URL project id must match the DSN
403ingest_cap_exceededHourly project cap hitWait or raise cap in project settings
404event_not_foundUser-feedback event_id unknownIngest the event first
413payload_too_largeBody over 2 MBShrink envelope/store body
500storage_errorPersist / DSN lookup / artifact writedocker compose logs epure; artifacts volume
503queue_unavailableIngest mpsc channel closedRestart epure

Body size: ingest router applies RequestBodyLimitLayer at 2 × 1024 × 1024 bytes.

Rate limits and valves

MechanismDefaultEffect
Spike valve100 raw events / minute / fingerprintStill 202; excess bodies not stored; issue counter increments
Project ingest cap5000 events / hour / project403 ingest_cap_exceeded
Login / register20 requests / IP / 60 s429 plain text

Spike saturation returns 202 Accepted, so clients see no error. Operators see elevated event_count without proportional stored event rows.

Ingest cap is checked before enqueue. Cap hits may also emit an internal alert (kind: ingest_cap_hit) for the dashboard Alerts rail.

There is no Redis-backed global rate limiter. Valves are in-process on the Rust binary.

Dashboard status codes

HTTPTypical causeWhat to do
400Invalid body (status, snooze mode, empty merge list, >200 trend IDs)Match the schema on Issues
401Missing/invalid sessionLogin again; check cookie Secure flag
404Issue / project not in session orgWrong org or deleted row
500Storage / unexpected server errordocker compose logs epure

Do ingest errors include CORS headers?

Successful ingest responses attach CORS headers when the request Origin is allowed. Error helpers that return early may omit CORS, so browser SDKs should treat any non-2xx as a failure.

202 but Issues still empty?

Not an error code. Accept is non-blocking, so persist may still be in the Tokio queue. Match the environment chip to the SDK tag, confirm the project that owns the DSN, then read docker compose logs epure. Verify lists the same matrix.

Why is there no Redis rate limiter?

The stack is two containers: Rust binary plus PostgreSQL 16. The token bucket and hourly counter live in-process. A saturated spike valve still returns 202, and the hourly cap returns 403 ingest_cap_exceeded. See Configuration.

What is the 2 MB cap?

The ingest router applies RequestBodyLimitLayer at 2 × 1024 × 1024 bytes, and anything larger returns 413 payload_too_large. Shrink the envelope or store body. Release file uploads share the same cap. This is separate from the spike valve, which still returns 202.

What does the spike valve do?

Default 100 raw events per minute per fingerprint, and clients still receive 202. Excess bodies are not stored while the issue counter increments. Operators then see elevated event_count without proportional stored rows, which is expected under a tight loop. The hourly project cap is the 403 path.