Reading Errors from the Extensions Page
Use the Errors view on chrome://extensions to find MV3 failures you never saw — manifest warnings, uncaught errors from every context, stack traces with context, and clearing noise.
Table of Contents
When an extension fails without anyone watching — the worker threw during a cold start, a content script hit an exception on a site you have never visited, a manifest key was ignored — the evidence usually still exists. Chrome collects uncaught errors from every extension context into one place, the Errors button on chrome://extensions, with the context, the file and line, and the stack. It is the closest thing an extension has to a crash log, and it is visible only in Developer mode, which is why so few people look at it. This guide is part of debugging extension contexts.
What the Errors view collects
Step-by-step
1. Turn on Developer mode and open the view
On chrome://extensions, toggle Developer mode (top right). An Errors button appears on each extension’s card when it has recorded at least one error. Clicking it opens a list, newest first.
Each entry shows the message, the context it came from (the worker, a page URL, or a content script on a specific site), a timestamp, and a stack trace whose frames link into the source.
2. Read the context before the message
The same message means different things in different contexts. “Cannot read properties of null” in the worker is a logic bug; in a content script on one website it is a site-specific DOM assumption; in the popup it may be a race with rendering.
1Uncaught TypeError: Cannot read properties of null (reading 'textContent')
2Context: https://news.example.com/article/4821
3Stack Trace:
4 content/main.js:88 (anonymous function)
Execution context: this is how a content-script error is shown — the “Context” line is the page URL, which immediately tells you the failure is site-specific. The same error with Context: sw.js would be in the worker.
3. Make your own errors show up with useful stacks
Errors thrown from minified bundles show minified stacks. Ship readable output to development builds and upload source maps separately for release — Chrome does not fetch maps for the Errors view.
1// vite.config.js
2export default {
3 build: {
4 minify: process.env.NODE_ENV === "production",
5 sourcemap: process.env.NODE_ENV === "production" ? "hidden" : true,
6 },
7};
Execution context: the build. In development builds the stack in the Errors view points at real function names and lines; in release builds you rely on your own reporting to symbolicate, as described in wiring Sentry into a Manifest V3 extension.
4. Turn silent failures into recorded ones
Caught errors never reach the view. An error swallowed by catch {} or by a promise chain without a rejection handler is invisible here and everywhere else.
1// Invisible:
2chrome.tabs.sendMessage(tabId, msg).catch(() => {});
3
4// Visible, and still non-fatal:
5chrome.tabs.sendMessage(tabId, msg).catch((err) => {
6 if (!/Receiving end does not exist/.test(err.message)) console.error("[sw] sendMessage failed", err);
7});
Execution context: the service worker. Ignoring the one expected rejection — no content script in the tab — and logging everything else with console.error puts genuine failures into the Errors view without flooding it. The expected case is covered in fixing “message port closed before response” errors.
5. Clear, reproduce, read
The view accumulates entries until cleared, and stale errors from a previous build are a common source of confusion. Clear it, reproduce the problem, and read only what the current build produced.
11. chrome://extensions → Errors → Clear all
22. Reload the extension (the circular arrow on its card)
33. Reproduce the issue with DevTools closed
44. Reopen Errors — everything listed is from this build and this run
Execution context: the browser’s extension management UI. Reproducing with DevTools closed matters because an attached inspector keeps the worker alive and hides lifecycle errors, as described in finding the right DevTools target for each context.
6. Check the manifest warnings at the top
Warnings about the manifest appear at the top of the card, not in the Errors list: unknown keys, unrecognised permissions, deprecated fields. They are easy to miss and occasionally explain a feature that silently does nothing.
1Unrecognized manifest key 'browser_specific_settings'.
2Permission 'offscreen' is unknown or URL pattern is malformed.
Execution context: shown on the extension card after install or reload. The first line is harmless in a shared manifest; the second, in a Chrome build, means the Chrome version is too old for the API — and chrome.offscreen will be undefined at runtime. Generating per-target manifests, as in generating a manifest per browser target, removes both.
When users are the ones seeing errors
The Errors view is a developer tool — users do not have Developer mode on and will not see it. But it is still useful for support: a user willing to follow three steps can copy an error for you.
A short, pre-written instruction in your support documentation works well:
11. Open chrome://extensions and turn on "Developer mode" (top right).
22. Find Reader and click "Errors".
33. Copy the first entry and paste it in your reply.
Execution context: support documentation, not code. The entry includes the context URL, which may reveal a site the user visited; say so in the instructions and let them redact it. For anything more than occasional support, an in-product “copy diagnostics” button that collects errors you logged yourself is kinder and more complete — the approach in diagnosing crashes from user reports.
Cross-browser variation
- Chrome / Edge: the Errors button on
chrome://extensions(Developer mode) collects uncaught errors, unhandled rejections andconsole.errorfrom all contexts, plus manifest warnings on the card. - Firefox: there is no single Errors view. Use
about:debugging→ Inspect for the background and extension pages, and the Browser Console (Ctrl+Shift+J), which shows errors from all extensions and content scripts with their source. - Safari: errors appear in the Web Inspector attached to each extension context under the Develop menu. There is no aggregated list.
- All three: caught errors are invisible to the browser’s tools. Anything you want to know about in production must be logged by your own code.
Verification
- Clear the Errors view, add
setTimeout(() => { throw new Error("probe") }, 0)to the popup script, open the popup, and confirm the error appears withpopup.htmlas its context. - Trigger a content-script error on a specific site and confirm its context line shows that site’s URL.
- Confirm the expected-rejection filter works — send a message to a tab with no content script and confirm nothing is logged:
1await chrome.tabs.sendMessage(tabId, { type: "ping" }).catch((err) => {
2 if (!/Receiving end does not exist/.test(err.message)) console.error(err);
3});
Execution context: the service worker console. No new entry should appear on the Errors page for this call.
- Reload a build with an unknown manifest key and confirm the warning appears on the card.
FAQ
Do errors persist across browser restarts?
Entries persist until cleared or the extension is reloaded or updated. Clear before reproducing so you are reading only current errors.
Why is console.error listed as an error when nothing threw?
Chrome records console.error calls from extension contexts in the same list. That is useful — it lets you surface caught-but-important failures — and a reason to reserve console.error for things that genuinely are errors.
Can I read these errors programmatically?
No. The view is browser UI only. Capture errors in your own code if you need them in a report or a dashboard.
Related
- Debugging a service worker that won’t start — the most dramatic error the view shows.
- Capturing uncaught errors in every context — getting the same information from users’ machines.
- DevTools differences across browsers — the Firefox and Safari equivalents.
- Debugging extension contexts — the parent guide.