---
title: "Browser errors, console logs and source maps"
description: "Capture redacted JavaScript errors and masked console logs, upload source maps from your build, and read grouped errors on the Issues page."
canonical_url: "https://noxtica.com/docs/observability/errors-and-source-maps/"
markdown_url: "https://noxtica.com/docs/observability/errors-and-source-maps/index.md"
last_updated: 2026-10-27
published: 2026-10-27
section: "observability"
section_title: "Observability"
site: "Noxtica"
language: "en"
source: markdown
---

# Browser errors, console logs and source maps

This page covers the three ways Noxtica records what goes wrong in a visitor's browser: error counts, redacted error detail and masked console logs. It also shows how to upload source maps so stack traces point at your original code. A tenant administrator sets the switches, a developer tags builds and uploads maps, and analysts read the results.

## What it is

Availability: Controlled availability, as part of real user monitoring. Each capture below has its own switch and is off by default. It runs when enabled for your organisation.

| Layer | What you get | Where you read it |
| --- | --- | --- |
| Error counts | Counts of uncaught errors and unhandled promise rejections, with no message or stack. They are part of [Real user monitoring and Web Vitals](https://noxtica.com/docs/observability/rum/). | Client RUM → Overview |
| Redacted error detail | One row per error occurrence: a redacted message summary and redacted stack-frame paths, with up to 20 frames kept. Raw error text is never stored. Errors are grouped, so the same fault counts once as a group with a number of occurrences. | Session Insights → Issues → Errors |
| Console logs | Masked console output from visitors' browsers at the levels `log`, `info`, `warn`, `error` and `debug`. | Client RUM → Console logs |
| Source maps | Your uploaded maps sit in a private store. The Issues page reads them at view time to show original file, line, column and name beside the raw frame. | Issues → stack trace |

Every capture follows the domain's privacy decision (consent, Do Not Track and Global Privacy Control, legal basis) and the visitor's `analytics` consent in consent-gated modes. Error detail also needs RUM Collection on and a domain sample rate above 0. See [Real user monitoring and Web Vitals](https://noxtica.com/docs/observability/rum/).

Source maps are never returned by any read route. The Issues page returns the resolved frame, not the map. If symbolication fails or is off, you see the raw frame, unchanged.

## Prerequisites

- **Extensions script.** Error detail and console logs come from the extensions script. See [Install & Browser Runtime](https://noxtica.com/docs/browser-runtime/).
- **RUM on.** RUM Collection is on and the domain has a sample rate above 0.
- **Privacy decision.** The domain has a recorded consent and Do Not Track decision.
- **Arming error detail.** Today a Noxtica operator is the sole role that can switch it on for a domain. Anyone who can manage the domain can switch it off again at any time, with no confirmation. Ask your account team to arm it.
- **Console logs.** The Admin role and a fresh step-up verification.
- **Source maps.** The Admin role to mint an upload token, with a fresh step-up verification. The domain's symbolication setting depends on your account: Backoffice has no switch for it today, so ask your account team to turn it on once maps are uploaded.
- **Reading.** The Viewer role or higher reads Issues and Client RUM.

## Steps

### 1. Tag your builds with release and build id

Source maps match errors by build id. Pass `release` (a label) and `buildId` (the immutable id of one deploy, for example a commit SHA) when you create the client yourself, in place of `data-auto-init`:

```js
const client = NoxticaCollector.createClient({
  siteKey: '<your-site-key>',
  release: '2026.10.27',
  buildId: '<commit-sha>',
});
```

- Each value is up to 128 characters from `A-Z a-z 0-9 . _ -`. An off-pattern value is dropped and never sent.
- The auto-initialised single-tag client has no attribute for these values. Without a `buildId`, errors are never symbolicated.
- A bare `release` label is not an artifact identity. Two deploys with the same label are told apart by `buildId`.

### 2. Turn on redacted error detail

Backoffice → Web Analytics & Privacy → **Tracking Allowlists** → **RUM trace controls** → **Redacted error-detail capture**.

1. Pick the domain.
2. Switch on **Capture redacted error detail on this domain**. Whoever switches it on confirms that the organisation records this as controller and that the domain's consent and lawful-basis settings cover it. Today that is a Noxtica operator.
3. Choose **Page URL capture** (below).

If the switch is on but nothing is captured, the card says **On, but not capturing** and names the cause: the workspace RUM switch is off, the sample rate is zero, the consent or Do Not Track policy is incomplete, a Do Not Track override has no recorded legal basis, or the domain neither requires consent nor has a legal basis.

Each domain stores up to 50,000 error occurrences a day. Retention defaults to 7 days and is set in step 7.

| Page URL capture | What is stored with an error or console line |
| --- | --- |
| Full (origin + path + redacted query), the default | The origin, path and a redacted query |
| Path only | Origin and path. The query is dropped. |
| Off | No page URL |

Query parameters that look like credentials or identifiers (`token`, `key`, `secret`, `password`, `auth`, `session`, `sig`, `code`, `otp`, `email`, `phone`) are stripped in every mode.

### 3. Turn on console-log capture

Backoffice → Web Analytics & Privacy → **Capture Policies** → **Browser console-log capture**.

1. Pick the domain.
2. Switch on **Capture browser console logs on this domain**.
3. Set **Sample rate (% of visits)**. The card shows the stored value in ppm, where 1,000,000 ppm is 100%.
4. Select **Save capture policy** and complete the step-up verification.

Messages are masked on the server before they are stored, and raw values are never stored. Limits:

| Limit | Value |
| --- | --- |
| Entries per request | 50 |
| Daily budget per device | 500 entries by default |
| Share of the budget for `log`, `info` and `debug` | 80%, so a later `error` or `warn` is not displaced |

Bounds can change. Backoffice shows the values in force.

### 4. Mint a source-map upload token

An upload token covers one build and one list of files. It lasts 10 minutes. An administrator mints it from a Backoffice session after a fresh step-up verification, because the token grants write access to the private store. Backoffice has no screen for this today, so the call is an API request:

```http
POST https://backoffice.noxtica.com/api/analytics/rum_source_maps/upload-authorizations
Content-Type: application/json

{
  "domainId": "<your-domain-id>",
  "buildId": "<commit-sha>",
  "release": "2026.10.27",
  "manifest": [
    { "filePath": "assets/app.js.map", "byteCount": 482113, "contentSha256": "<64-hex-sha256>" }
  ]
}
```

A response of `201` carries `token` and `expiresAt`. Rules: `buildId` uses `A-Z a-z 0-9 . _ -` up to 128 characters. `release` also allows `/` and runs to 256 characters. The manifest holds 1 to 500 files. `byteCount` is the exact size in bytes, and `contentSha256` is the lowercase SHA-256 of the file.

An unattended CI job cannot pass step-up verification by itself. Run the mint as an approved operator, then hand the short-lived token to the build.

### 5. Upload the maps from your build

Send each file in the manifest once, with the token as a bearer credential. No session is needed.

```bash
curl -X POST \
  "https://backoffice.noxtica.com/api/analytics/rum_source_maps/upload?filePath=assets%2Fapp.js.map" \
  -H "Authorization: Bearer <upload-token>" \
  --data-binary @dist/assets/app.js.map
```

A success returns `{ "ok": true, "status": "active" }`. Repeating an upload returns `already_active`, so a retried build is safe. Do not deploy `.map` files to your public host. Remove them from the deploy output once every file has uploaded.

Limits in force by default:

| Limit | Default |
| --- | --- |
| Size of one map | 10 MiB |
| Maps per release | 100 |
| Active bytes per tenant | 2 GiB |
| Active releases per tenant | 20 |

These values are configuration and can change. A rejected upload names the limit.

### 6. List or delete maps

`GET https://backoffice.noxtica.com/api/analytics/rum_source_maps` lists active maps for the tenant. Add `?build_id=<id>` to filter. It needs the Viewer role. `DELETE .../rum_source_maps/<map-id>` removes one map. It needs the Admin role and a fresh step-up verification.

### 7. Read errors and set retention

Backoffice → Session Insights → **Issues**.

- **Errors tab.** Errors are grouped with counts, affected sessions and users where recorded, and a redacted stack trace. The **Behavior** tab holds rage-click and similar groups. See [Behavior analytics: heatmaps, journeys and funnels](https://noxtica.com/docs/observability/behavior-analytics/).
- **Window.** Choose 1, 7, 14, 30 or 90 days. A window never shows more than the error-detail retention keeps, 7 days by default.
- **Filters.** Search by text, type, route, severity, release, build, platform, browser, operating system and device type. **URL contains** needs at least 2 characters.
- **Severity.** Severity is a deterministic rule on occurrences times affected users, with 1 when users are not recorded: 1,000 or more is Critical, 100 or more High, 10 or more Medium, otherwise Low. Checkout, payment and billing routes have a High floor. No AI grading is involved.
- **New and Ongoing.** New means the group started inside the window, within retained history.
- **Detail.** The drawer has Overview, Stack trace and Context. **Watch replay** opens a linked replay, which exists when the occurrence recorded an exact link to a retained, consented session. **Copy link** copies the address.

Backoffice → Web Analytics & Privacy → **RUM Data Lifecycle** shows what each lane holds and its retention. Set **Retention (days, 1–90)** for error details per domain. The default is 7 days, which is also the platform window: a longer value does not keep error details longer. The page also offers a permanent **Purge** for console logs, error details and replay. A purge cannot be undone.

Backoffice → Session Insights → Client RUM → **Console logs** lists masked lines. Filter by **Level**, **Window**, **Search message** (2 characters or more), **Page URL**, **Device ID** or **Replay session ID**. **Export** downloads CSV, JSON or text after a step-up verification.

## Verify it works

1. Throw a test error on a page of the domain, for example `setTimeout(() => { throw new Error('noxtica-test') })`. Sampling can skip a visit, so repeat it if nothing appears.
2. Open Issues → Errors. The error appears with an occurrence count. If the card is empty, **Review capture settings** opens the switches.
3. After uploading maps for the same `buildId`, open the group. The stack trace shows the original file, line and column beside the raw frame.
4. Call `console.warn('noxtica-console-test')` on the page. The line appears under Client RUM → Console logs. Any masked part of a message shows as `[REDACTED]`.

## Troubleshooting

| Symptom | Cause | Fix |
| --- | --- | --- |
| **No runtime errors** on Issues | Error detail is off, or a gate of the card **On, but not capturing** is closed. | Check each cause listed on the card in step 2. |
| Errors show raw frames after you uploaded maps | The error has no `buildId`, the `buildId` differs from the upload, or the domain's symbolication setting is off. | Pass `buildId` in step 1, match it in the manifest, and ask your account team about symbolication. |
| Console logs tab is empty | Capture is off, the sample rate is 0, or no entry arrived in the window. | Check step 3 and widen the window. |
| A console message shows `[REDACTED]` | The server masked part of the value before storing it. | None. The original value was never stored. |
| Upload returns `401` `unauthorized` or `expired` | The token is missing, malformed or older than 10 minutes. | Mint a new token. |
| Upload returns `403` `file_not_in_manifest` | The `filePath` does not match a manifest entry exactly. | Use the same string as in the manifest. |
| Upload returns `400` `byte_count_mismatch` or `content_hash_mismatch` | The file differs from what the manifest declared. | Recompute size and SHA-256 from the final file. |
| Upload returns `413` or `409` | A size limit, release limit, tenant byte limit or active-release limit was reached. | Delete old maps or ask your account team. `quota_race` is safe to retry. |
| Upload returns `503` | Map storage is not ready for your account. | Ask your account team. |
| Some console lines are missing | The device used its daily budget, or low-severity lines reached their 80% share. | None. The budget is counted per device and per UTC day. |

## Related

- [Real user monitoring and Web Vitals](https://noxtica.com/docs/observability/rum/) — the RUM switches this page relies on.
- [Session replay: setup, masking and playback](https://noxtica.com/docs/observability/session-replay/) — the Replay session ID filter links console lines to a recording.
- [Data subject scope, erasure requests and account deletion](https://noxtica.com/docs/compliance/requests-and-deletion/) — erasure requests for people.
- [Privacy](https://noxtica.com/privacy/) — the public privacy policy.
