Skip to content

Interop: UUID project ids in DSNs break all JS-family SDKs (validateDsn requires numeric; digit-leading UUIDs silently truncate) #328

Description

@ajianaz

What

The Sentry SDK DSN parser (@sentry/core utils/dsn.js, all JS SDKs) validates that the DSN projectId is fully numeric (^\d+$ in validateDsn()), and truncates digit-leading project ids to their leading digits (projectId.match(/^\d+/) in dsnFromString()). TrapFall issues DSNs whose project id is a UUID (e.g. https://<key>@trapfall.ajianaz.dev/2e3c789d-98cc-4cee-b0d1-6ed51cab436b). Consequences for every JS-family SDK:

  • Digit-leading UUID (about half of all UUIDv4): SDK truncates the project id to the leading digit run (2e3c789d-...2) and POSTs to /api/2/envelope/ → TrapFall 404s → silent event loss.
  • Letter-leading UUID: SDK treats the DSN as invalid → client no-ops → silent event loss (nothing is ever sent).

Verified empirically with @sentry/bun 10.75.2 against a local stub ingest (SDK 10.75.2, 2026-09-22):

DSN projectId SDK behavior On-wire path
123456 (numeric) accepted /api/123456/envelope/
2e3c789d-98cc-... (digit-leading UUID) truncated, accepted /api/2/envelope/
a3f8e2c1-98cc-... (letter-leading UUID) rejected — no request at all

TrapFall itself routes by the literal project-id path segment (confirmed: full-UUID path = 200, any other path = 404), so a correct DSN from the SDK is all that is missing.

Impact

Every JS-family SDK consumer with a TrapFall-issued UUID DSN silently loses all events. (Rust SDK is unaffected — sentry::types::Dsn accepts any project-id string.)

Suggested fix (either side works;TrapFall-side is the one we control)

  1. TrapFall (recommended): issue DSNs whose project path segment is all-digits — e.g. derive a numeric display id per project (slug hash or a short numeric id column) and render DSNs as https://<key>@host/<numeric-id>/, keeping the UUID for the dashboard/API. This makes stock SDKs of every language work unchanged.
  2. Alternatively document a required bridge (tunnel + X-Sentry-Auth header) for JS consumers — currently what gatehouse ships — but per-app bridging does not scale.

Related: auth-side interop gap is filed separately (query-param sentry_key → 401).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions