Sentry envelope keep/drop verify on Epure (202 empty Issues)
sentry envelope keep drop verify
Epure keeps event items, discards transaction, skips replay/profile/session. Verify 202 then Issues; store vs envelope bisect; CORS and PUBLIC_URL rows.
On this pageShowHide
Epure is exception-only ingest: envelope event items are persisted; transaction items are discarded; replay_*, profile*, session, attachment, and check_in are skipped. No event item returns 400 invalid_envelope. Success is 202 Accepted plus { "id" }, then an unresolved Issues row. Empty Issues after 202 usually means env filter, wrong project, or worker flush.
You already run official @sentry/browser or @sentry/node against a two-container self-host (Rust binary + PostgreSQL 16) and need to know which envelope items become Issues. Full Sentry self-host with Relay/Kafka workers that persist tracing and replay is the undesired alternative for this path. This how-to is the verify path: keep/drop honesty, then store -> envelope -> SDK -> CORS bisect.
Unique wedge: Epure exception-only item handling from the Envelope docs table. event persisted; transaction discarded; replay_* / profile* / session / attachment / check_in skipped. Bias disclosed: Epure first-party docs are the source of truth for Epure behavior; Sentry envelope docs describe a fuller item surface.
Primary how-to: Envelope. Acceptance: Verify. Pin/init: Quickstart. Host shape: Installation. Symptom matrix: Troubleshooting. Env: Configuration. Sibling context: Sentry SDK compatible, Spike valve fingerprint flood, Two-container error tracking, Epure vs Sentry.
Keep vs drop items
Epure parses, queues, and persists envelope event items only. transaction items are discarded because the product is exception-only. attachment, session, replay_*, profile*, check_in, and other item types are skipped. An envelope with no event item returns 400 invalid_envelope.
event
- Behavior (Envelope)
- Parsed, queued, persisted
transaction
- Behavior (Envelope)
- Discarded (exception-only product)
attachment, session, replay_*, profile*, check_in, other
- Behavior (Envelope)
- Skipped
| Dimension | Behavior (Envelope) |
|---|---|
| event | Parsed, queued, persisted |
| transaction | Discarded (exception-only product) |
| attachment, session, replay_*, profile*, check_in, other | Skipped |
Ingest success stays 202 { "id" } when non-event items are present but skipped or discarded. Do not invent per-item HTTP status codes beyond the Envelope table and response section.
202 but empty Issues
A successful ingest returns 202 Accepted plus { "id" } before the Issues row appears. If Issues stays empty, wait about 1 second (Verify) or about 500 ms (Troubleshooting), match the environment filter to your SDK tag (often local), confirm the project that owns the DSN, and check docker compose logs epure. Empty feed copy can read 0 UNRESOLVED EXCEPTIONS when nothing is unresolved.
202 but Issues empty
- Fix (Verify / Troubleshooting)
- Wait ~1s / ~500 ms; filter `local`; correct project; `docker compose logs epure`
Env chip mismatch
- Fix (Verify / Troubleshooting)
- Match environment filter to `Sentry.init` (`local` / `production` / all)
Wrong project
- Fix (Verify / Troubleshooting)
- Open host or `EPURE_PUBLIC_URL`; select project that owns DSN
Flood still 202, Issues quiet
- Fix (Verify / Troubleshooting)
- Spike valve - send slower unique exception or wait; not a failed verify
Cookie / login loop on HTTP
- Fix (Verify / Troubleshooting)
- `EPURE_SESSION_SECURE=0` for local HTTP (session path, not DSN ingest)
| Dimension | Fix (Verify / Troubleshooting) |
|---|---|
| 202 but Issues empty | Wait ~1s / ~500 ms; filter `local`; correct project; `docker compose logs epure` |
| Env chip mismatch | Match environment filter to `Sentry.init` (`local` / `production` / all) |
| Wrong project | Open host or `EPURE_PUBLIC_URL`; select project that owns DSN |
| Flood still 202, Issues quiet | Spike valve - send slower unique exception or wait; not a failed verify |
| Cookie / login loop on HTTP | `EPURE_SESSION_SECURE=0` for local HTTP (session path, not DSN ingest) |
Store vs envelope
POST /api/{project_id}/envelope/ takes application/x-sentry-envelope (newline-delimited, <= 2 MB). POST /api/{project_id}/store/ takes JSON (or gzip/zlib via Content-Encoding) <= 2 MB. Both use DSN auth and return the same 202 { "id" } success shape. Malformed envelope with no event -> 400 invalid_envelope; malformed store -> 400 invalid_store. Over 2 MB -> 413 payload_too_large on both.
Path
- Envelope
- `POST /api/{project_id}/envelope/`
- Store (legacy)
- `POST /api/{project_id}/store/`
Content-Type
- Envelope
- `application/x-sentry-envelope`
- Store (legacy)
- `application/json` (or gzip/zlib)
Body
- Envelope
- Newline-delimited <= 2 MB
- Store (legacy)
- JSON event <= 2 MB
Auth
- Envelope
- DSN
- Store (legacy)
- Same DSN
Success
- Envelope
- 202 + `{ "id" }`
- Store (legacy)
- Same 202 + `{ "id" }`
Malformed
- Envelope
- 400 `invalid_envelope`
- Store (legacy)
- 400 `invalid_store`
Session cookie
- Envelope
- Ignored
- Store (legacy)
- Ignored
| Dimension | Envelope | Store (legacy) |
|---|---|---|
| Path | `POST /api/{project_id}/envelope/` | `POST /api/{project_id}/store/` |
| Content-Type | `application/x-sentry-envelope` | `application/json` (or gzip/zlib) |
| Body | Newline-delimited <= 2 MB | JSON event <= 2 MB |
| Auth | DSN | Same DSN |
| Success | 202 + `{ "id" }` | Same 202 + `{ "id" }` |
| Malformed | 400 `invalid_envelope` | 400 `invalid_store` |
| Session cookie | Ignored | Ignored |
Bisect order
Bisect documented order: (1) store JSON curl (smallest wire path), (2) envelope fixture curl, (3) SDK captureException, (4) if the browser fails CORS, OPTIONS curl plus EPURE_CORS_ORIGINS. Session cookies on envelope or store do nothing; DSN belongs on ingest, not on /api/v1/*.
Baseline store curl (Verify / Envelope seed defaults):
curl -sS -D - -o /tmp/epure-ingest.json -X POST "http://localhost:8080/api/550e8400-e29b-41d4-a716-446655440000/store/" -H "X-Sentry-Auth: Sentry sentry_version=7, sentry_key=a1b2c3d4e5f6g7h8i9j0, sentry_secret=supersecretdevkey" -H "Content-Type: application/json" -d '{"platform":"javascript","exception":{"values":[{"type":"Error","value":"Epure try-it"}]}}'
Expected (Verify success table / Envelope): HTTP/1.1 202 Accepted + { "id": "<uuid>" }, then an unresolved issue for that exception type.
Envelope fixture curl (from repo root after seed-dev):
curl -sS -D - -o /tmp/epure-envelope.json -X POST "http://localhost:8080/api/550e8400-e29b-41d4-a716-446655440000/envelope/" -H "X-Sentry-Auth: Sentry sentry_version=7, sentry_key=a1b2c3d4e5f6g7h8i9j0, sentry_secret=supersecretdevkey" -H "Content-Type: application/x-sentry-envelope" --data-binary @fixtures/sentry/browser/envelope.txt
Expected (Envelope): HTTP/1.1 202 Accepted + { "id": "..." }.
SDK one-liner (Verify): Sentry.captureException(new Error("Epure verify test"));
When showing install lines, pin @sentry/browser@7.120.0 or @sentry/node@7.120.0 (Quickstart).
CORS and PUBLIC_URL
Browser CORS failures mean the origin is not in EPURE_CORS_ORIGINS; recreate the epure service after changing it. OPTIONS on the envelope path should return 200 or 204 with Access-Control-Allow-Origin. Set EPURE_PUBLIC_URL for ngrok, custom host, or production HTTPS; for local plain HTTP login loops set EPURE_SESSION_SECURE=0 (session path, not DSN ingest).
OPTIONS preflight (Troubleshooting):
curl -sS -D - -o /dev/null -X OPTIONS "http://localhost:8080/api/${PROJECT_ID}/envelope/" -H "Origin: http://localhost:5173" -H "Access-Control-Request-Method: POST" -H "Access-Control-Request-Headers: X-Sentry-Auth, Content-Type"
Production-shaped vars (Configuration example): EPURE_PORT=8080, EPURE_PUBLIC_URL=https://errors.example.com, EPURE_CORS_ORIGINS=https://app.example.com, plus POSTGRES_PASSWORD, EPURE_INGEST_PASSWORD, and EPURE_APP_PASSWORD set to non-default secrets.
Caps and spike valve
Default project ingest cap is 5000 events per hour; over that returns 403 ingest_cap_exceeded before enqueue. Flooding the same fingerprint (~100+/min) still returns 202 and bumps counters while duplicate bodies may drop: that is the spike valve, not a failed verify. For flood economics and bill-shock framing, read Spike valve fingerprint flood; this article does not remake that angle.
Other documented ingest failures (Verify / Envelope): 401 invalid_dsn; 403 dsn_revoked; 403 project_mismatch; 503 queue_unavailable.
Who should use what
Use this guide if you already point official Sentry SDKs at a two-container Epure host and need to know which envelope items become Issues. Read sibling posts for DSN-swap scoreboard, spike-valve flood economics, or two-container host shape. Stay on Sentry Cloud if session replay or APM is the daily debug loop.
Use this guide if
- You already point official Sentry SDKs at a 2-container Epure host and need keep/drop honesty for envelope items.
- You see 202 Accepted but empty Issues and need the env-chip / project / worker checklist.
- You want the store -> envelope -> SDK -> CORS bisect order from first-party docs.
Read something else if
- You still need the DSN-only swap / SDK subset scoreboard: Sentry SDK compatible.
- You are sizing flood economics: Spike valve fingerprint flood.
- Session replay or APM is the daily debug loop: stay on Sentry Cloud (Epure vs Sentry).
Limitations
Epure is not 100% Sentry compatible. Session replay, APM tracing, and profiling are not Epure features (transaction discarded; replay_* / profile* skipped). Redis, Kafka, and ClickHouse are not default Epure services. Stack is two Compose services: Rust binary + PostgreSQL 16 (postgres:16-alpine). Cloud is not live.
Negative scope (must-read):
- Epure is not 100% Sentry compatible.
- Session replay, APM tracing, and profiling are not Epure features.
- Symbolicator is not an Epure component.
- Redis, Kafka, and ClickHouse are not default Epure services for this path.
- Cloud is not live.
- This article does not quote fixture byte contents, idle RAM figures, rustc semver, or image digests.
- Do not remake the spike-valve bill-shock ArticlePost from this pack.
Deep links: Envelope | Verify | Quickstart | Installation | Troubleshooting | Configuration.