Chrome Extension Common Errors and How to Fix Them

7 min read

Chrome Extension Common Errors and How to Fix Them

Developing Chrome extensions can be rewarding, but encountering errors is part of the process. Understanding the most common errors and their solutions will save you hours of frustration. This guide covers the errors you’ll most likely face during extension development and provides proven solutions.

Manifest Version Errors

The manifest.json file is the backbone of your extension, and errors here prevent your extension from loading entirely.

Error: “Manifest version 2 is not supported”

If you see this error, your extension is using Manifest V2 which Chrome no longer supports for new extensions. Manifest V2 extensions were deprecated in 2022 and are no longer accepted in the Chrome Web Store.

Solution: Migrate to Manifest V3. Update your manifest.json:

{
  "manifest_version": 3,
  "name": "My Extension",
  "version": "1.0",
  ...
}

Key changes include replacing background pages with service workers, updating content script injection methods, and adjusting API calls.

Error: “Required key ‘permissions’ not found”

This error indicates your manifest.json is missing required fields or has syntax errors.

Solution: Validate your manifest structure. Ensure all required fields are present:

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

Error: “Permission ‘tabs’ requires manifest_version 3”

Some permissions require Manifest V3. If you’re seeing permission-related errors, ensure you’re using the correct manifest version.

Solution: Upgrade to Manifest V3 and use the new permission declarations. For example, “scripting” permission replaces some old patterns.

Runtime Errors

Runtime errors occur while your extension is executing and can be harder to diagnose.

Error: “Unchecked runtime.lastError: Could not establish connection”

This typically happens when trying to communicate between extension contexts (popup to content script, background to popup) when the connection cannot be established.

Solution: Ensure you’re checking for connection availability before sending messages:

// Always check for runtime.lastError
chrome.runtime.sendMessage(message, (response) => {
  if (chrome.runtime.lastError) {
    console.error(chrome.runtime.lastError.message);
    return;
  }
  // Handle response
});

For content scripts, ensure the tab exists and the script has been injected:

chrome.tabs.sendMessage(tabId, message, (response) => {
  if (chrome.runtime.lastError) {
    // Handle case where content script hasn't loaded yet
  }
});

Error: “Extension context invalidated”

This occurs when you try to use a Chrome API after the extension context has been destroyed, commonly in service workers that have been terminated.

Solution: Always check if the context is still valid before making API calls:

try {
  chrome.storage.local.get('key', (result) => {
    // Use result
  });
} catch (e) {
  if (e.message.includes('Extension context invalidated')) {
    // Handle re-initialization
  }
}

For service workers, implement proper lifecycle handling and reconnect logic.

Error: “Cannot access contents of the page”

This permission error occurs when your content script doesn’t have access to the current page.

Solution: Add the appropriate host permissions in your manifest:

{
  "permissions": ["activeTab"],
  "host_permissions": ["<all_urls>"]
}

Or use the activeTab permission for extensions that only need access when the user invokes them.

Content Script Errors

Content scripts run in the context of web pages and have unique constraints.

Error: “Cannot read properties of undefined”

This often occurs when trying to access page elements before they exist or when the page structure differs from expectations.

Solution: Wait for the DOM to be ready or use a mutation observer:

// Wrap in DOMContentLoaded
document.addEventListener('DOMContentLoaded', () => {
  const element = document.querySelector('.my-element');
  if (element) {
    // Safe to manipulate
  }
});

// Or check for element existence
const element = document.querySelector('.my-element');
if (element) {
  element.textContent = 'Hello';
}

Error: “Refused to execute inline script”

This CSP (Content Security Policy) error occurs when your extension tries to execute inline JavaScript.

Solution: Move inline scripts to external files or use the appropriate Manifest V3 approach:

<!-- Instead of inline script -->
<script src="content-script.js"></script>

<!-- In manifest.json -->
"content_scripts": [
  {
    "matches": ["<all_urls>"],
    "js": ["content-script.js"]
  }
]

Error: “Content script cannot modify page CSS”

Some websites use Shadow DOM which isolates styles, making it impossible for content scripts to affect certain elements.

Solution: Use declarativeNetRequest rules or inject styles into shadow roots:

// For shadow DOM elements
const hostElement = document.querySelector('#shadow-host');
const shadowRoot = hostElement.attachShadow({mode: 'open'});
shadowRoot.innerHTML = '<style>:host { color: red; }</style>';

Storage and Sync Errors

Error: “QUOTA_BYTES quota exceeded”

You’ve exceeded the storage quota for chrome.storage.

Solution: Monitor your storage usage and implement cleanup:

chrome.storage.local.getBytesInUse((bytes) => {
  console.log(`Using ${bytes} of ${chrome.storage.local.QUOTA_BYTES} bytes`);
});

// Implement cleanup for old data
chrome.storage.local.set({ data: newData }, () => {
  // Remove old keys to free space
});

Error: “Storage sync is not available”

Storage.sync isn’t available in certain contexts like incognito mode or some enterprise environments.

Solution: Implement fallback to local storage:

const setStorage = (key, value) => {
  if (chrome.storage.sync) {
    return chrome.storage.sync.set({ [key]: value });
  }
  return chrome.storage.local.set({ [key]: value });
};

Service Worker Errors

Error: “Service Worker startup failed”

Service workers fail to start due to uncaught errors or syntax issues in your background script.

Solution: Add comprehensive error handling:

// At the top of your service worker
self.addEventListener('error', (event) => {
  console.error('Service worker error:', event.error);
});

self.addEventListener('unhandledrejection', (event) => {
  console.error('Unhandled promise rejection:', event.reason);
});

Error: “Service Worker terminated due to inactivity”

Service workers are automatically terminated after about 30 seconds of inactivity.

Solution: Use chrome.alarms to keep the service worker alive when needed:

chrome.alarms.create('keep-alive', { periodInMinutes: 0.8 });
// This prevents the service worker from idling out

Conclusion

These common errors cover the majority of issues you’ll encounter during Chrome extension development. Remember to always check the console in both the extension context and the DevTools for your target pages. The Chrome extension documentation is an excellent resource for understanding API-specific errors and best practices. With this troubleshooting knowledge, you’ll be able to debug issues quickly and keep your extensions running smoothly.

No previous article
No next article