Repository navigation
Report frontend errors to a Netlify function - #799
Merged
Merged
Conversation
✅ Deploy Preview for jolly-shaw-20fe62 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
mikeghen
approved these changes
Nov 11, 2026
The app showed errors to the user and logged them to the browser console, but had no way to tell us about them. Errors caught by the global handlers (Vue's error handler, the error event and unhandledrejection) now go through one capture function, which reports the error and shows the notification as before. Some catch blocks that handle an error without showing it also report it, with a label naming the block. Reports go to a new function at /api/client-error, which writes each one to the function's logs as a single line starting with "client_error ". A report holds the error's name, code, message and stack, the commit the app was built from, the route name, the network, the connected wallet's name and the locale. The function adds the browser and OS family from the user agent, and doesn't log the IP address. Before a report is sent, the app removes addresses, keys, signatures and other long hex strings, ENS and other domain names, email addresses and amounts, and reduces URLs other than the app's own to their host. The function applies the same rules again, since anyone can call it. Both are tested against one shared set of examples. Only production builds send reports. User rejections, messages the app already ignores and errors that come only from extensions or injected wallet scripts are left out. The same error is sent once per page load, and no more than 10 reports per page load. The function accepts requests up to 16 KB and is rate limited per IP. Reporting is on by default and can be turned off with a new toggle in the footer's Settings section, in all three locales. Clearing local storage keeps that choice. The privacy policy now describes the reports and how long they're kept. The invalid private key error no longer repeats the key that was entered, so it can't reach logs or reports. The list of messages that aren't worth showing moved to errors.ts so the reporter can share it. Prettier now formats .mjs files like .js files.
ENS names can contain letters in any script, emoji, and symbols such as $ and '. The scrubbers now find names by their dots rather than by the characters they contain. A run of text between spaces, quotes, brackets and similar delimiters that contains a dot becomes <name>, unless its last label starts with a digit, as in a decimal. Some umbra-js errors quote the recipient the user entered, which might not contain a dot. The scrubbers now replace the recipient in those messages first. Unchanged text between matches is kept together, so later rules, such as the one for amounts with thousands separators, still see it whole. The frontend and the function apply the same rules. The shared examples add names in several scripts, emoji sequences, quoted names and the umbra-js messages, and a new test follows two of these messages from the reporter to the function's log.
The reporter leaves out errors whose stack frames all come from other origins, since the browser's error and unhandledrejection events also see errors from browser extensions and injected wallet scripts that have nothing to do with the app. Wallets often reject a request with an error created in their own script, and ethers passes it on unchanged, so the error has only the wallet's frames even when the app made the request. Apply that filter only to errors from the error and unhandledrejection events. Errors from Vue's error handler and from catch blocks that call reportError come from the app's own operations, so they're reported whatever their frames. User rejections and ignored messages are still left out for every source. Tests cover each source, and a wallet error passed on by ethers' Web3Provider.
apbendi
force-pushed
the
client-error-reporting
branch
from
November 11, 2026 16:07
ab97fa0 to
f50cb5f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The app showed errors to the user and logged them to the browser console, but had no way to tell us about them. Errors caught by the global handlers (Vue's error handler, the error event and unhandledrejection) now go through one capture function, which reports the error and shows the notification as before. Some catch blocks that handle an error without showing it also report it, with a label naming the block.
Reports go to a new function at /api/client-error, which writes each one to the function's logs as a single line starting with "client_error ". A report holds the error's name, code, message and stack, the commit the app was built from, the route name, the network, the connected wallet's name and the locale. The function adds the browser and OS family from the user agent, and doesn't log the IP address.
Before a report is sent, the app removes addresses, keys, signatures and other long hex strings, ENS and other domain names, email addresses and amounts, and reduces URLs other than the app's own to their host. The function applies the same rules again, since anyone can call it. Both are tested against one shared set of examples.
Only production builds send reports. User rejections, messages the app already ignores and errors that come only from extensions or injected wallet scripts are left out. The same error is sent once per page load, and no more than 10 reports per page load. The function accepts requests up to 16 KB and is rate limited per IP.
Reporting is on by default and can be turned off with a new toggle in the footer's Settings section, in all three locales. Clearing local storage keeps that choice. The privacy policy now describes the reports and how long they're kept.
The invalid private key error no longer repeats the key that was entered, so it can't reach logs or reports. The list of messages that aren't worth showing moved to errors.ts so the reporter can share it. Prettier now formats .mjs files like .js files.