# Troubleshooting

## No events are sent

Check consent first. `unknown` and `denied` intentionally create no events. For
JavaScript, inspect `getConsent()`; for Flutter, inspect `analytics.consent`.

Call `flush()` and inspect its result. JavaScript returns an outcome; Flutter
returns the acknowledged count. `getDiagnostics()` reports queue eviction and
permanent server rejection counts.

## HTTP 401

The write key is missing, invalid, expired, or paired with a `click_id` that does
not belong to the app's tenant and offer. Generate or rotate the key through the
admin API. Do not replace it with an admin JWT.

## HTTP 400

The envelope, timestamp, event name, screen, or property failed server
validation. Current SDKs sanitize properties before persistence; confirm the
application is not constructing ingestion requests manually.

## HTTP 429 or temporary server failure

The SDK keeps the same event UUID and postpones the batch. It respects a numeric
`Retry-After` header and otherwise uses bounded exponential backoff. Do not create
a second SDK instance to force delivery.

## Web initialization fails during server rendering

Create the browser SDK only from client code. `window`, `localStorage`, Web
Crypto, and browser `fetch` are not available in every server-rendering phase.

## Browser storage is unavailable

Private modes, user settings, or quota exhaustion can make Web Storage throw.
Keep the website usable, leave analytics disabled, and route the error through
the application's operational logging without attaching personal data.

## Local HTTP is rejected

HTTP is allowed only for `localhost`, `127.0.0.1`, or `::1`. All other endpoints
must use HTTPS.

## Events remain after a process restart

That is expected until acknowledgement or a permanent rejection. If the user
revokes consent, call `setConsent('denied')` or the Flutter equivalent; use
`reset()` when the application must also erase anonymous identity.
