Ver en Español
How to Debug Chrome Extensions: A Step by Step Guide
Jun 24, 2026
Updated: Jun 25, 2026

How to Debug Chrome Extensions: A Step by Step Guide

Debugging Chrome extensions can be a challenge, especially for those just starting out in extension development. In this post we'll explore how to effectively debug your Chrome extensions and solve the most common problems that can come up during development. Let's go through it step by step.

Getting Started with Debugging

Manifest file: The manifest.json file is crucial for any Chrome extension. A very common mistake is having an incorrect configuration in this file.

A typical error example: make sure the properties are spelled correctly. For instance, the permissions property must be plural and the manifest version must be accurate.

These days Chrome only runs extensions built with Manifest V3. Manifest V2 was phased out gradually through 2024 and 2025, and it no longer works on any browser channel. That's why your manifest must always declare "manifest_version": 3. As you may remember from earlier chapters in this series, we dedicated a whole chapter to Manifest V3, so here we follow that same line.

{
    "name": "My Extension",
    "version": "1.0",
    "manifest_version": 3,
    "permissions": ["tabs"]
}

Common manifest errors:

  • Incorrect permissions: make sure permissions are in an array, not an object.
  • Versions: when you update your extension, increment the version number appropriately to reflect major or minor changes.
  • Outdated manifest version: if you're coming from an old extension with "manifest_version": 2, you must migrate it to version 3, because MV2 no longer runs.

Debugging the Service Worker

In Manifest V3, the background script was replaced by a Service Worker. It can shut down when it's not in use, which sometimes makes debugging harder: if you open it and see no activity, it may simply be idle.

Inspecting the Service Worker:

  1. Open chrome://extensions/ and turn on Developer mode in the top right corner.
  2. Find your extension and click the "Inspect views: service worker" link. This opens DevTools connected directly to the Service Worker, with its console and breakpoints.
  3. For a low level view of every registered Service Worker, visit chrome://serviceworker-internals. From there you can see their state, stop them, or force them to start.

Reactivating the Service Worker: reload the extension from chrome://extensions/ (the reload button) to make sure the Service Worker is active again, and watch its state in the console to confirm it's running.

Note: the Service Worker idle timeout was extended compared to the first MV3 releases. As long as there are active message or event ports, the inactivity timer resets, so a Service Worker that's processing messages won't shut down mid task. This greatly improves the debugging experience over the early MV3 versions.

Using the chrome.runtime Library

The chrome.runtime library is essential for handling messages and events within your extension.

Connection errors: a very common error is "Could not establish connection. Receiving end does not exist.". It usually shows up when sending messages between the Service Worker, content scripts, and the popup.

The most frequent real causes are:

  • No listener is registered. The receiving end must register chrome.runtime.onMessage. If that listener doesn't exist, there's no one to receive the connection.
  • The content script hasn't been injected yet. If you call chrome.tabs.sendMessage on a tab before its content script has loaded, there's no receiver ready. Make sure the tab and content script are available before sending the message.

The fix: register the listener on the receiver and verify the target is ready before sending. In Manifest V3, chrome.runtime.sendMessage supports promises, so I recommend using the promise based version instead of callbacks, because it makes error handling much clearer.

// Receiver: register the listener
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === "PING") {
    sendResponse({ ok: true });
  }
});

// Sender: promise based sendMessage (MV3)
const response = await chrome.runtime.sendMessage({ type: "PING" });
console.log(response);

Debugging the Extension Popup

The extension popup is the interface users see when they interact with your extension. It's important to make sure it works correctly.

Opening the developer tools:

  • Right click the popup and select "Inspect" to open Chrome DevTools connected to the popup.
  • Use the "Console" tab to see errors and console.log messages.

Debugging AJAX and the network: use the "Network" tab to monitor requests and make sure the responses are what you expect.

Debugging the Content Script

The content script interacts directly with web pages. To debug it:

Developer console:

  1. Open the page's developer tools and go to the "Sources" tab.
  2. Select your content script and use breakpoints to pause execution and inspect the state of the DOM.

Monitoring Permissions

Make sure your extension has the right permissions to carry out the operations it needs.

Declaring permissions: in the manifest.json file, declare all the permissions you need.

{
    "permissions": ["tabs", "storage", "contextMenus"]
}

Note: tabs is a fairly broad permission. If you only need access to the active tab when the user interacts with your extension, prefer activeTab: it asks less of your users and reduces the permission surface Chrome shows at install time.

Reviewing Other People's Extensions

To learn and get inspiration, you can review the code of other installed extensions.

Accessing installed extensions:

  • On macOS: Library/Application Support/Google/Chrome/Default/Extensions.
  • On Windows: C:\Users\[YourUser]\AppData\Local\Google\Chrome\User Data\Default\Extensions.

Analyzing the code: examine files like manifest.json and the scripts to understand how they work and how they're structured.

Suggested exercises

  1. Take a sample extension with "manifest_version": 2 and migrate its manifest to Manifest V3, adjusting the background script into a Service Worker.
  2. Deliberately trigger the "Could not establish connection. Receiving end does not exist." error by messaging a tab with no content script, then fix it by registering an onMessage listener.
  3. Swap the tabs permission for activeTab in a simple extension and verify it still works for your use case.

3-point summary

  1. In 2026 Chrome only runs Manifest V3 extensions, so your manifest must always declare "manifest_version": 3.
  2. Debug the Service Worker from chrome://extensions/ with "Inspect views: service worker", and check chrome://serviceworker-internals for low level control.
  3. Most messaging errors come from a missing onMessage listener or a content script that hasn't been injected; use the promise based chrome.runtime.sendMessage for clearer error handling.

I hope this post helped you better understand how to debug your Chrome extensions. If you have any questions or need more details, don't hesitate to leave a comment. See you next time!

Sebastian Gomez

Sebastian Gomez

Creador de contenido principalmente acerca de tecnología.

Leave a Reply

0 Comments

Advertisements

Related Posts

Categorias