Back to Blog

How to Debug Your Chrome Extension: The Complete Guide

Learn how to debug your Chrome extension step by step. Fix popup, service worker, and content script issues with practical debugging techniques for Manifest V3.

MM

Michael McGarvey

April 3, 2026·4 min read
Developer debugging a Chrome extension with DevTools

Your Chrome extension installs fine. The icon appears in the toolbar. But when you click it, nothing happens. No error in the console. No crash. Just silence. You open DevTools on the page and see nothing because the extension runs in a completely different context. This is the moment most developers realize that debugging a Chrome extension is not like debugging a web app.

The core challenge is that a Chrome extension is not one program. It is several programs running in isolated environments that communicate through message passing. Your popup, background service worker, and content scripts each have their own console, their own errors, and their own DevTools window. If you are looking in the wrong place, you will never find the bug. Once you understand where each piece of your extension runs and how to inspect it, debugging becomes straightforward. If you are still setting up your first extension, start with how to create a Chrome extension from the ground up before diving into debugging.

1.

2.

3.

4.

5.

6.

7.

Why Chrome Extension Debugging Is Different

A normal web app runs in one page with one DevTools window. A Chrome extension splits its logic across at least two or three separate execution contexts. The popup is its own small HTML page that opens and closes every time the user clicks the icon. The background service worker runs without any visible page at all. Content scripts run inside the web page the user is viewing, but in an isolated JavaScript environment that cannot directly access the page's variables.

Each of these contexts has its own console. A console.log in your service worker will never appear in the popup's DevTools. An error in your content script will not show up on the chrome://extensions page. This is why so many developers think their code is not running when it actually is. They are just looking in the wrong console.

Debugging the Popup

Right-click your extension icon in the toolbar and select "Inspect popup." This opens a DevTools window attached specifically to your popup's HTML page. You will see your console logs, network requests, and any errors that occur while the popup is open.

The most common popup issue is that it closes the instant you click anywhere outside of it, which also closes the attached DevTools window and clears everything you were looking at. To work around this, add a debugger statement in your popup code. When DevTools hits the breakpoint, the popup stays open. Alternatively, you can log to the background service worker using chrome.runtime.sendMessage and inspect those logs in the service worker console instead.

If your popup opens as a blank white rectangle, the problem is almost always a wrong file path in your manifest's default_popup field or a build step that is not outputting your popup HTML to the expected directory. Check your manifest first, then check your build output folder.

Debugging the Background Service Worker

Open chrome://extensions in your browser, find your extension, and click the "service worker" link. This opens DevTools for your background script. Any console.log, error, or network request from the service worker appears here.

The biggest gotcha with Manifest V3 service workers is that they stop running when idle. If you open the service worker DevTools and see an empty console, it is probably because the worker terminated and restarted since your last log. Anything logged before the restart is gone. To catch errors that happen at startup, add your logging at the very top of your service worker file so it executes immediately when the worker spins up.

If you see "service worker registration failed" on the chrome://extensions page, the problem is usually a syntax error in your service worker file or a missing file reference. Click the error link for details, fix the syntax, and reload the extension. For extensions built with React and TypeScript, a misconfigured build that outputs ES modules instead of a plain script will also cause this error. See how to build a Chrome extension with React and TypeScript for the correct build setup.

Debugging Content Scripts

Content scripts run inside the web page, so you debug them using the page's own DevTools. Right-click the page, select "Inspect," and open the Sources panel. Look for your extension's content script files under the "Content scripts" section in the left sidebar. You can set breakpoints, step through code, and inspect variables just like any other JavaScript.

The most common content script bug is trying to access a DOM element that has not loaded yet. If your script runs at document_start, the page body may be empty. Switch to document_idle in your manifest or wrap your logic in a DOMContentLoaded listener. The second most common issue is message passing failures between the content script and the background service worker. If chrome.runtime.sendMessage silently fails, check that your service worker has a matching chrome.runtime.onMessage listener and that the extension has not been reloaded since the content script was injected.

Common Errors and How to Fix Them

Permission errors show up as "Cannot access contents of url" or similar messages. These mean your manifest is missing a required host permission or the activeTab permission for the page you are trying to interact with. Add the specific host to your manifest's permissions array and reload.

Content Security Policy violations appear when your extension tries to load external scripts, use eval, or inline event handlers. Manifest V3 enforces a strict CSP by default. Move any inline scripts into separate files and avoid eval entirely. If you need to load an external resource, fetch it from your service worker and pass the data to your popup or content script.

Messaging errors like "Could not establish connection. Receiving end does not exist" mean the listener for your message is not registered. This usually happens when a content script sends a message but the service worker has gone idle, or when the popup sends a message to a content script on a tab where the content script was never injected. Always check that both sides of a message channel are active before sending.

ExtensionFast

Ship Your Chrome Extension This Weekend

ExtensionFast gives you auth, payments, and a landing page out of the box — so you can focus on your unique features, not the boilerplate.

Chrome extension built fast with ExtensionFast
Wand iconGet ExtensionFast

Tools That Make Debugging Easier

The chrome://extensions page is your command center. Enable "Developer mode" in the top right corner to see the "Reload" button, error logs, and the service worker inspector link for each extension. After every code change, click "Reload" to pick up the new version instantly without uninstalling and reinstalling.

For extensions that modify web pages, use the Elements panel in the page's DevTools to verify that your content script is actually changing the DOM. If you are injecting UI elements, inspect them to make sure styles are not being overridden by the host page's CSS. Using a Shadow DOM for injected UI isolates your styles and prevents conflicts.

Add structured error logging early. A simple pattern is to wrap your key functions in try-catch blocks that log errors with context, such as which function failed and what arguments it received. When you have hundreds of users and cannot reproduce a bug locally, these logs are the only way to diagnose the issue. For tracking errors in production, consider integrating a lightweight error reporting service or the Google Analytics Measurement Protocol to send error events from your extension.

Ship With Fewer Bugs From Day One

Most debugging pain comes from misconfigured manifests, incorrect file paths, and permission mismatches. These are setup problems, not logic problems. They burn hours because they produce silent failures instead of clear error messages. The fastest way to avoid them is to start with a foundation that is already configured correctly.

ExtensionFast gives you a production-ready Manifest V3 project with the service worker, popup, and content script wiring already set up and tested. Permissions are minimal by default, the build pipeline outputs files exactly where Chrome expects them, and the project structure keeps each execution context cleanly separated so you always know where to look when something goes wrong. Instead of debugging your build configuration, you can focus on debugging your actual feature logic. If you want to get your extension reviewed and approved quickly after debugging, read how to pass the Chrome Web Store review on your first try.

You can skip the setup and start building your core vision today with ExtensionFast.

Newsletter

Build smarter, ship faster

Weekly tips on Chrome extension development, marketing, and monetization.