github ↗ sign in

open source error monitoring for javascript

Errors happen.

One script tag. Every uncaught error and rejected promise on your site is captured, grouped, and explained by AI before your users report it.

● uncaught error · shop.example

TypeError: Cannot read properties of null
  (reading 'textContent')
    at renderProfile (js/app.js:12:20)
    at HTMLButtonElement.<anonymous> (js/app.js:51:9)

url      /profile?id=5&token=[Filtered]
seen     ×37 · grouped into 1 issue

● errlens ai · confidence: medium

renderProfile() reads .textContent from an element that is not on the page, so querySelector() returned null.

// suggested fix
const el = document.querySelector('#profile');
if (!el) return;
el.textContent = user.name;

We tell you why.

01 / pipeline

From crash to fix

  1. capture

    The browser throws

    A 7 KB script listens for uncaught errors and rejected promises. It never throws itself and sends at most 10 events per page.

    addEventListener('error')
  2. filter

    Secrets stay home

    Tokens, passwords and keys in the URL are replaced before sending, and again on the server. No cookies, no form data.

    ?token=[Filtered]
  3. group

    One bug, one row

    A fingerprint ignores line numbers and build hashes, so the same bug stays one row after every deploy.

    sha256(msg + frame)
  4. explain

    AI reads the stack

    Only new errors go to Claude. The answer must match a JSON schema and is validated before it is saved.

    { cause, fix, code }
02 / specs

Spec sheet

03 / try it

Break this page

Press the button. It throws a real JavaScript error, the same way a bug on your site would. Press it again and watch the repeat get grouped instead of logged twice.

listening for errors…

1 block = 1 issue 1 layer = 1 occurrence explained by ai

04 / install

One line

Create a project, allow your domain, paste the tag into <head>. That is the whole setup.

index.html — my-shop● unsaved
1<!doctype html>
2<html>
3<head>
4  <meta charset="utf-8">
5  <title>My shop</title>
6  
7</head>
8<body>
9  <button id="buy">Buy now</button>
10  <script src="app.js"></script>
11</body>
12</html>
https://my-shop.example/cart

Wireless keyboard
$49.00

USB-C cable
$9.00

Uncaught TypeError: Cannot read properties of undefined (reading 'total')
at checkout (app.js:88:21)
errlens — my-shop · errors● live
new

TypeError: Cannot read properties of undefined (reading 'total')
app.js · checkout · just now

×1

↳ errlens ai · confidence: high

checkout() reads cart.total before the cart has loaded, so cart is still undefined when the button is clicked.

if (!cart) return showLoading();
const total = cart.total;
POST /api/v1/ingest · 202
  1. 01 paste
  2. 02 deploy
  3. 03 it breaks
  4. 04 you get the fix
</> <script src="https://errlens.hsnvusal.online/sdk.js" data-key="pk_…" async></script>
05 / privacy

What leaves the page

this is all that is sent POST /api/v1/ingest

{
  "type": "error",
  "message": "TypeError: cart is undefined",
  "stack": "at checkout (app.js:88:21)",
  "url": "/cart?id=5&token=[Filtered]",
  "browser": { "language": "en-US", "screen": "1440x900" }
}

[Filtered] tokens, passwords and keys in the url are removed before sending, and again on the server.

never sent

  • cookies
  • form input
  • page content
  • local storage

Your visitor's ip is only hashed for rate limits and never stored.

Stop guessing. Start fixing.