# Troubleshooting

> No errors showing, CSP blocks, duplicates, 429 limits, an unreachable node and sign-in problems — step-by-step checks.

Work through the section that matches what you see. Most problems are found within the first three checks.

## No errors arrive

### 1. Is the SDK running?

- `init` returns `true` when it runs. Add `debug: true` temporarily: the SDK then logs its decisions, including an invalid DSN, to the console.
- The DSN must be this project's DSN, copied as a whole: `https://<public-key>@ingest.belvador.dev/<project-id>`. No quotes inside, no trailing slash.
- `disabled: true`, `BELVADOR_DISABLED=1` or `sampleRate: 0` switch sending off.

### 2. Does the request leave the app?

In the browser, open the network tab and trigger a test error. Look for a `POST` to `https://ingest.belvador.dev/api/<project-id>/envelope/`.

- **No request at all** — the error was caught before the SDK saw it (see [Handled errors](#errors-my-framework-handles-never-arrive)), or `init` did not run.
- **Blocked by CSP** — the console shows a `Content-Security-Policy` violation. Add `https://ingest.belvador.dev` to `connect-src`.
- **Blocked by an ad or privacy blocker** — the request fails with no status. Test in a clean browser profile.

### 3. What did the edge answer?

| Status | Meaning | Fix |
|---|---|---|
| `200` | Accepted. Continue at step 4. | — |
| `401` | Missing or invalid key | Copy the DSN again from the project; the key may be revoked |
| `403` | Project mismatch, rejected, or **origin not allowed** | Add your site to **Allowed origins** or leave the list empty — see [Projects and DSN](https://belvador.dev/en/docs/projects-and-dsn#allowed-origins) |
| `413` | Too large | An event is limited to 1 MiB, an attachment to 5 MiB |
| `415` | Unsupported compression | Use the Belvador SDK or a current Sentry SDK |
| `429` | Rate-limited, over the monthly quota, or the node's buffer is full | Read the `Retry-After` header; see [Limits](#429-too-many-requests) |
| `503` | Temporary problem at the edge | The SDK retries on its own |

After a `401` or `403`, Belvador's SDK stops sending for the life of that page or Worker isolate — reload after fixing.

### 4. Accepted but not visible?

- Check **Project settings → Intake, last 24 hours**: if **Received** goes up, the error reached Belvador.
- Is the **node Healthy**? If it is **Unreachable**, errors are held at the edge and appear once it reconnects — see [Node health](https://belvador.dev/en/docs/node/health#when-the-node-is-unreachable).
- Check the issue filters: status **Unresolved** and period **24 hours** are the defaults, and the environment filter may hide yours.
- Was it a tracing or session item rather than an error? Those are counted as **Not supported yet** and not stored.

### The Connection tab says Not verified or Problem

**Not verified** means no connection check arrived yet — run the one for your platform from [Verify the connection](https://belvador.dev/en/docs/sdk/verify). **Problem** lists what is wrong and what to do; every code is explained on that page. With `debug: true` the SDK also prints a diagnostic code in the console.

### The intake path check never arrives

**Check intake path** on the Connection tab sends one event from your node through the public ingest path; it does not test your app. If it does not arrive within about 10 seconds, the node is usually not connected: open **Node** and check its status.

## Errors my framework handles never arrive

Frameworks often catch errors to show a nice error screen — the SDK then never sees them.

| Where | What to wire |
|---|---|
| React render errors | `ErrorBoundary`, and on React 19 the three root hooks — [React](https://belvador.dev/en/docs/sdk/react) |
| Router error screens (React Router `errorElement`, …) | `captureException(error)` inside the error screen |
| TanStack Start route errors | `createRouter(withBelvadorRouter({ ... }))` — [TanStack Start](https://belvador.dev/en/docs/sdk/tanstack-start) |
| Vue, Angular, Svelte error hooks | `captureException` from the framework's error hook |
| Your own `try … catch` | `captureException(error)` where you still want to know |

## TanStack Start: only browser errors arrive

- `belvadorRequestMiddleware` and `belvadorFunctionMiddleware` must be **last** in `requestMiddleware` and `functionMiddleware`.
- `src/server.ts` must wrap the entry that actually serves requests, and `vite.config.ts` must point `tanstackStart.server.entry` at it.
- The Worker needs `nodejs_compat`.
- Not reported by design: `redirect()`, `notFound()`, errors with a status below 500, and 500 responses you return without throwing.
- Errors in route loaders during SSR are usually reported from the browser only — a known limitation.

## Every error arrives twice

- An old `@sentry/*` setup or `Sentry.init` call is still running next to Belvador. Remove it.
- The same error is reported by two of your own hooks, for example a `try … catch` that calls `captureException` and then re-throws to a boundary that reports again. Report in one place.
- Two projects receive the same app because two DSNs are configured in different files.

## Errors are grouped wrongly

- **Too many separate issues** for one bug: messages contain values Belvador does not normalise — set a [fingerprint](https://belvador.dev/en/docs/issues#your-own-grouping).
- **Different bugs in one issue**: they share a stack, for example one generic error handler. Report with more specific fingerprints or exception types.

## Stack traces show minified code

See [Source maps](https://belvador.dev/en/docs/source-maps#check-that-it-works): the `release` must match, the deployed files must be the injected ones, and the upload must have succeeded.

## Sensitive data appears in an event

1. **Rotate the exposed secret first.** Removing it from Belvador does not undo the exposure.
2. Check **Project → Privacy → Built-in detectors**: every group should be on.
3. Find where it came from — a tag, context, message or attachment — and stop sending it, or drop it in `beforeSend`.
4. Read [what filtering cannot guarantee](https://belvador.dev/en/docs/privacy#what-filtering-cannot-guarantee).

## 429: too many requests

| Reason | What happens | Fix |
|---|---|---|
| `rate_limited` | The project's **Events per second** or **Burst** was exceeded | Usually a loop reporting the same error — fix it, or raise the project limit up to the plan |
| `quota_exceeded` | The workspace's monthly envelope limit is used up | Sending resumes at the start of the next month (UTC) |
| `buffer_full` | The node is unreachable and its edge buffer is full | Bring the node back — [Node health](https://belvador.dev/en/docs/node/health#when-the-node-is-unreachable) |

## A monitor shows no runs

1. Run the job once and watch its output: with `debug: true` the SDK logs `BLV_MONITOR_INVALID_SLUG`, `BLV_MONITOR_INVALID_REASON` or `BLV_MONITOR_CONFIG_INVALID` when it refuses to send.
2. Check the slug on the Monitors page matches the one in your code, letter for letter, in the same project.
3. Check-ins from a browser are refused on purpose. Send them from the server or with `curl` — see [HTTP check-ins](https://belvador.dev/en/docs/monitors/http).
4. With `curl`, read the status code: `401` is a wrong key or project, `429` a rate limit.
5. A slug that is not a monitor yet appears under **Found in code** when the project does not allow monitors from code.

## A monitor says Not observable

Belvador could not watch that time: the node was offline or catching up, or check-ins were rate limited or over the monthly quota. Runs are not marked missed for that time. Once the node is back it waits up to 10 minutes for buffered check-ins, then judges again. See [When Belvador cannot see](https://belvador.dev/en/docs/monitors/overview).

## A monitor says Missed but the job ran

- The job may report to another **environment** than the one the monitor watches: check the environment tabs on the monitor.
- The schedule's time zone may differ from the scheduler's. The create form shows the next deadlines in both the monitor's time zone and yours.
- The grace period may be too short for the job's start delay; raise **Grace period**.

## 429 for check-ins

Check-ins have their own limit, separate from errors: 60 per monitor and environment per minute, plus a monthly quota per plan. A loop that sends a check-in per item should send one heartbeat per batch instead — see [Watching background work](https://belvador.dev/en/docs/guides/background-work).

## CORS errors after turning on traces

The API on another origin must allow `traceparent` and `sentry-trace` in `Access-Control-Allow-Headers`. Narrow `tracePropagation.targets` to your own APIs, or allow the headers — see [Link errors across tiers](https://belvador.dev/en/docs/sdk/tracing).

## The node is not healthy

See [Node health](https://belvador.dev/en/docs/node/health) for every status and reason. If the machine is gone, use **Replace machine & restore** — [Updates and rebuilds](https://belvador.dev/en/docs/node/updates#replace-machine-and-restore).

## Sign-in and two-factor

- **“Your session has ended. Sign in again.”** — sign in again; sessions expire.
- **Lost authenticator** — use a recovery code on the code screen: [Account security](https://belvador.dev/en/docs/account-security#lost-your-phone).
- **“Incorrect or expired code.”** — check your phone's clock is set automatically; codes depend on the time.
- **“This action needs two-factor authentication.”** — set up two-factor in Account security, then try again.

## Messages you may see

| Message | Meaning |
|---|---|
| The node is not ready yet. Try again when it shows Healthy. | The action needs a running node |
| The node is not connected right now… | It will pick up the request once it reconnects |
| That time range is too large to read quickly. | Narrow the period or filters |
| You have reached the limit for this workspace. | A plan limit, such as the number of workspaces |
| This project has no active DSN key. | Create one in Project settings → DSN keys |
| The node could not send the test event through ingest. | Check the node is connected on the Node page |
| Too many requests. Wait a moment and try again. | Too many changes in a short time |

Errors in the app show a reference ID. If you contact support at hello@belvador.dev, include it — never include tokens, passwords or recovery codes.
