Guided debugging for common Chrome Extension issues including service worker, message passing, content script, and storage problems
Guides debugging of Chrome Extension issues including service worker, messaging, content scripts, and storage.
/plugin marketplace add francanete/fran-marketplace/plugin install chrome-extension-expert@fran-marketplaceGuided debugging for issue type: {{issue}}
Based on the issue type, follow the appropriate debugging guide and analyze the extension code.
1. Service Worker Not Registering Check:
background.service_worker pathtype: "module" if using ES imports// Correct manifest configuration
{
"background": {
"service_worker": "background.js",
"type": "module" // Only if using ES modules
}
}
2. Service Worker Terminating
chrome.alarms for periodic tasks// BAD - Will lose state
let cachedData = null;
// GOOD - Persist to storage
chrome.storage.session.set({ cachedData: data });
3. Events Not Firing
// BAD - Won't work
setTimeout(() => {
chrome.runtime.onMessage.addListener(...);
}, 1000);
// GOOD - Top level registration
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
// Handle asynchronously inside
});
chrome://extensions1. "Receiving end does not exist" Causes:
// Safe message sending
async function sendToTab(tabId, message) {
try {
return await chrome.tabs.sendMessage(tabId, message);
} catch (error) {
if (error.message.includes('Receiving end does not exist')) {
// Inject content script first
await chrome.scripting.executeScript({
target: { tabId },
files: ['content.js']
});
return await chrome.tabs.sendMessage(tabId, message);
}
throw error;
}
}
2. Async Response Not Working
Must return true from listener for async responses:
// WRONG - Response never sent
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
fetch(url).then(data => sendResponse(data));
// Missing return true!
});
// CORRECT
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
fetch(url).then(data => sendResponse(data));
return true; // CRITICAL for async
});
3. Port Disconnected Long-lived connections close after 5 minutes of inactivity or when the other end closes.
chrome.runtime.lastError1. Script Not Injecting Check:
matches pattern in manifest is correct{
"content_scripts": [{
"matches": ["*://*.example.com/*"],
"js": ["content.js"],
"run_at": "document_idle"
}]
}
2. Script Runs But Nothing Happens
// Ensure DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
3. Cross-Origin Restrictions Content scripts can't make cross-origin requests. Use background script as relay.
1. Data Not Persisting
// Check what's actually stored
const all = await chrome.storage.local.get(null);
console.log('All storage:', all);
2. Sync Storage Quota Exceeded
// Check usage
const usage = await chrome.storage.sync.getBytesInUse(null);
console.log('Sync usage:', usage, '/ 102400');
3. Storage Not Syncing
chrome.storage.sync specificallychrome.storage.onChanged1. Side Panel Not Appearing Check:
sidePanel permission in manifestside_panel.default_path set correctly{
"permissions": ["sidePanel"],
"side_panel": {
"default_path": "sidepanel.html"
}
}
2. Can't Open Programmatically
// Must be in response to user action
chrome.action.onClicked.addListener((tab) => {
chrome.sidePanel.open({ tabId: tab.id });
});
3. State Lost When Panel Closes Side panel is recreated each time. Use storage:
// Save state before unload
window.addEventListener('beforeunload', () => {
chrome.storage.session.set({ panelState: currentState });
});
// Restore on load
const { panelState } = await chrome.storage.session.get('panelState');
chrome://extensions for errors (red badge)Now analyze the extension code for {{issue}} issues and provide specific debugging recommendations.