Updated July 2026 | 6-minute read | By the PlugThis team
Why Chrome Extensions Fail in Manifest V3 comes down to one root cause: developers treating MV3 like a simple version bump when it is, in fact, a fundamental architectural redesign. Manifest V2 was disabled in stable Chrome starting October 10, 2024, replaced by MV3's ephemeral service workers, the declarativeNetRequest blocking API, and a ban on remote-hosted code. Chrome began auto-disabling Manifest V2 extensions in stable builds in October 2024, and the enterprise policy that let organizations keep them running was removed with Chrome 139 in mid-2025. If your extension is broken, disabled, or rejected from the Chrome Web Store in 2026, the failures all trace back to a handful of known, avoidable mistakes.
The good news: over 85% of actively maintained extensions in the Chrome Web Store are now running Manifest V3. Understanding exactly why Chrome extensions fail is the fastest path to shipping something that actually works.
"MV3 is a fundamentally different programming model. The service worker lifecycle changes everything. Design for statelessness from day one, and treat the service worker as an unreliable intermediary that might not be running when you need it." — Developer reflection after migrating 17 Chrome extensions to Manifest V3
What Manifest V3 Actually Changed
MV3 made four structural changes that break extensions built with MV2 assumptions: persistent background pages became ephemeral service workers that Chrome can shut down at any time; the blocking webRequest API was replaced by declarativeNetRequest (DNR); remote-hosted code was banned; and host permissions were tightened.
The Four Breaking Structural Changes
| What Changed | MV2 Behavior | MV3 Behavior | Common Failure Mode |
|---|---|---|---|
| Background execution | Persistent background page, always alive | Ephemeral service worker, terminated after ~30s idle | State loss, silent crashes |
| Network interception | Blocking webRequest API |
Declarative rules via declarativeNetRequest |
Request blocking stops working |
| Remote code | Could load scripts from CDNs or remote URLs | All code must be bundled inside the extension package | Store rejection at review |
| Host permissions | Declared in permissions array |
Moved to separate host_permissions field; users can restrict at runtime |
Extension silently loses site access |
- Service worker termination: Service workers are terminated after roughly 30 seconds of inactivity, and any state stored in global variables is lost.
- Blocking webRequest removal: The
webRequestBlockingpermission is no longer available — usedeclarativeNetRequestinstead. - Remote code ban: An extension can only run JavaScript that is included within its own package.
- Host permission separation: In MV3, users can restrict host access at runtime, meaning even a correctly declared permission may be overridden by the user.
Key Takeaway: MV3 is not MV2 with a higher version number. These four changes create cascading problems throughout the extension lifecycle. For more on this, see Chrome Extension Builder For Entrepreneurs 2026 Guide.
The Service Worker State Problem
The single most common reason why Chrome extensions fail after migrating to MV3 is treating the service worker like a persistent background script. Any data stored in memory-scope variables simply disappears when the service worker terminates — silently, and without an error message the extension can catch.
How State Loss Manifests
A real example: subscription-checking code that stored a user's payment status in a global variable. After the service worker restarted, the variable was undefined, and paid users saw free-tier limitations.
- Global variable loss: Do not store state in module-scope variables — persist it in
chrome.storage. - Missing DOM APIs:
window,document,XMLHttpRequest, andlocalStorageare gone inside the service worker. Usefetchandchrome.storageinstead. - Async listener registration: Register event listeners synchronously at the top of the file, not inside async callbacks.
- WebSocket connections: WebSocket connections die when the service worker sleeps — move persistent connections to content scripts where possible.
- Polling intervals: The
chrome.alarmsAPI enforces a minimum period of 1 minute in production. If your subscription refresh used a 30-second polling interval, in production it silently upgrades to 60 seconds.
The correct rule: Treat the service worker as a function that runs, does its job, and may be killed before it finishes. Every piece of data your extension needs across events must live in
chrome.storage.localorchrome.storage.session— never in aletvariable.
Key Takeaway: Persistent in-memory state is architecturally incompatible with MV3. Rebuild every background data operation around chrome.storage from the start.
Remote Code, Permissions, and Store Rejections
Beyond state loss, Manifest V3 migration issues cluster around three other failure points: the ban on remote-hosted code, overly broad permission declarations, and Chrome Web Store review rejections. Each of these issues stops an extension from ever reaching users.
Remote Code Ban
A core requirement for Manifest V3 is that extensions may no longer use remotely-hosted code. All code must be bundled with the extension; external scripts from CDNs are no longer allowed for security reasons.
Permissions That Trigger Rejection
MV3 extensions face stricter review — Google flags extensions with broad permissions like <all_urls>. Two extensions were rejected for requesting activeTab and <all_urls> together, which was considered redundant.
- Overly broad host permissions: Requesting
<all_urls>when your extension only needs access to one domain triggers a manual review warning and significantly increases rejection probability. - Redundant permissions: Declaring both
activeTaband full host permissions for the same URL pattern is flagged as excessive and can result in automatic rejection. - Missing
host_permissionsfield: In MV3, URL match patterns must live inhost_permissions, not inside the mainpermissionsarray. - Permission warning overload: Multiple warnings on installation reduce user installation likelihood. Consider implementing optional permissions or a less powerful API.
| Failure Type | Root Cause | How It Appears | Fix |
|---|---|---|---|
| Store rejection | Remote-hosted JS or eval() | Policy violation email from Google | Bundle all code; remove CDN imports |
| Store rejection | Overly broad permissions | Rejection citing excessive host access | Scope permissions to specific domains |
| Silent runtime failure | URL patterns in wrong manifest field | Extension loads but has no site access | Move patterns to host_permissions |
| User abandonment | Too many install-time warnings | Low install conversion in the Web Store | Use optional permissions requested at runtime |
Key Takeaway: Declare only the permissions your extension needs for its core function, and defer optional permissions using chrome.permissions.request() at the moment the user triggers a feature that requires them.
The declarativeNetRequest Learning Curve
For any extension that intercepts, modifies, or blocks network requests, the shift from the blocking webRequest API to declarativeNetRequest (DNR) is the most disorienting part of Manifest V3. The extension hands Chrome a set of static rules ahead of time, and Chrome's own engine does the matching without ever running extension code per request. This is faster and more privacy-preserving by design, but more constrained.
- Rule count limits: The maximum is 100 static rulesets (since Chrome 120), with 50 enabled simultaneously, and 300,000 total static rules shared across all extensions.
- Dynamic rule ceiling: Dynamic rules — those added at runtime — are capped at 5,000 per extension.
- No per-request JavaScript: Logic that previously inspected request headers, cookies, or response bodies inline is no longer possible with DNR alone.
- CacheStorage blind spot: DNR only applies to requests that reach the network stack — it may not cover responses that go through a service worker's
onfetchhandler.
Google increased the number of rulesets for declarativeNetRequest, allowing extensions to bundle up to 330,000 static rules and dynamically add a further 30,000.
Key Takeaway: Plan your network logic as declarative rules from the design phase. Extensions that require real-time, per-request JavaScript decisions need a fundamentally different architecture in MV3.
Chrome Extension Troubleshooting: Diagnosing Failures in 2026
If an extension suddenly broke after a manifest change, start by checking whether it is disabled, unsupported, corrupted, or simply missing the right site access.
Diagnostic Decision Tree
- Check chrome://extensions first: Chrome auto-disables an extension after an update for five distinct reasons, and the red text under the extension tells you which one.
- MV2 disabled message: If an extension shows "no longer supported," it was caught in the 2024–2025 rollout because the developer never shipped a Manifest V3 version.
- Sideloaded extension blocked: An extension installed from a .crx file or registry entry rather than from chromewebstore.google.com will be auto-disabled.
- Service worker unresponsive: Navigate to
chrome://serviceworker-internalsto confirm whether the extension's service worker is registered. - Permissions silently denied: Open DevTools for the extension's service worker (
chrome://extensions→ Inspect views → service worker) and check the console for permission errors.
| Symptom | Likely Cause | Where to Check | Resolution |
|---|---|---|---|
| Grey icon, red text | MV2 or policy violation | chrome://extensions | Install MV3 version or find alternative |
| Icon present, nothing happens | Service worker terminated or unregistered | chrome://serviceworker-internals | Re-enable extension; redesign for statelessness |
| Works on some sites, not others | Host permissions revoked by user | Extension details page → Site access | Request runtime permissions explicitly |
| Works in dev, fails in production | Remote code or eval() blocked | DevTools console errors | Bundle all scripts; remove remote imports |
| Stale data shown to users | State stored in service worker variable | Code review | Migrate all state to chrome.storage |
Key Takeaway: Read the exact error text at chrome://extensions first. Each failure type has a different fix.
Manifest V3 Best Practices: Building Extensions That Don't Break
The developers whose extensions do not fail in 2026 designed for MV3's constraints from the start rather than migrating against them. Most day-to-day pain points share one root cause: MV3 assumes ephemeral, event-driven background code.
The Non-Negotiable MV3 Best Practices
- Design for statelessness: Assume the service worker is not running. Every event handler must reconstruct necessary context from
chrome.storage. - Register listeners synchronously: Service workers must register event listeners synchronously during initial execution.
- Use
chrome.alarmsfor recurring work:setIntervaldoes not reliably keep running in a service worker. - Bundle everything: Remove all CDN script references. Every JavaScript file must be included in the package.
- Minimize permissions: Request only what the core extension function requires at install time. Use
chrome.permissions.request()at runtime for feature-specific permissions. - Stage your rollout: After converting to Manifest V3, test with a limited audience first before full release.
Where PlugThis Fits
For founders, product managers, and non-technical builders who need a working MV3 extension without managing this complexity manually, PlugThis handles the MV3 architecture automatically. PlugThis lets you describe the extension you want in plain English and get back production-ready Manifest V3 code with a real backend and source code you own. The MV3 compliance that trips up developers with years of experience is handled by default. For more on this, see Best Chrome Extension Builders With Backend Support 2026.
Key Takeaway: Write less imperative background code, rely more on declarative rules and persistent storage APIs, and test the service worker lifecycle as a first-class concern.
Conclusion
Every failure in 2026 traces back to one of five root causes: service worker state loss, remote code use, overly broad permissions, misuse of the network interception APIs, or a missing structural redesign of the background execution model.
- Service worker state is ephemeral: Use
chrome.storage.localfor anything your extension needs to survive across events. - MV2 is gone: As of June 2026, MV2 is effectively dead on Chrome.
- Remote code is prohibited: Bundle every JavaScript dependency inside the extension package.
- Permissions need precision: Declare only what is necessary, move URL patterns into
host_permissions, and defer optional permissions to runtime requests. - Build MV3-first, not MV3-migrated: Extensions designed around MV3's constraints from the start do not fail the way migrated extensions do. Tools like PlugThis generate production-ready MV3 extensions by default.
The fastest path forward is to stop treating MV3 as a constraint and start treating it as the specification. Extensions built to the spec ship, get approved, and stay working when Chrome updates.
FAQ
Why do Chrome extensions fail in Manifest V3?
Chrome extensions fail in Manifest V3 primarily because it is an architectural redesign. The five main failure points are: (1) ephemeral service workers replace persistent background pages, causing state loss if data is stored in global variables instead of chrome.storage; (2) the blocking webRequest API is removed, requiring a switch to declarativeNetRequest; (3) a ban on remote-hosted code means all scripts must be bundled; (4) stricter permission rules cause store rejections for overly broad requests; and (5) host permissions must be moved to a separate host_permissions field.
Is Manifest V2 still supported in Chrome in 2026?
No. By June 2026, Manifest V2 is effectively dead for ordinary users. Chrome began auto-disabling MV2 extensions in October 2024, and the enterprise policy that allowed organizations to maintain them was removed with Chrome 139 in mid-2025.
What replaced the background page in Manifest V3?
A service worker replaces the extension's background or event page. Service workers are terminated by Chrome after inactivity (roughly 30 seconds) and have no access to DOM APIs such as window, document, or localStorage. All persistent state must use chrome.storage.
Why does my Manifest V3 extension get rejected by the Chrome Web Store?
The most common rejection causes are: loading JavaScript from remote URLs or CDNs; requesting overly broad host permissions like <all_urls>; declaring redundant permissions; and large bundle sizes that trigger manual policy review.
What is the declarativeNetRequest API and how does it replace webRequest?
The chrome.declarativeNetRequest API blocks or modifies network requests by specifying declarative rules. Instead of writing JavaScript that fires on every request, developers define a JSON rule file that Chrome's own engine evaluates natively — with no extension code running per request. This is faster but removes the ability to make dynamic, per-request decisions in code.
How do I fix a Chrome extension that stops working after a Chrome update?
First, check chrome://extensions and read the red text beneath the extension. If the extension is MV2-based, the only durable fix is finding or building an MV3 version. If the service worker is unresponsive, check chrome://serviceworker-internals. If permissions are silently failing, inspect whether the user has restricted host access on the extension's details page.
Can non-developers build Manifest V3 Chrome extensions without coding?
Yes. Tools like PlugThis are built specifically for this use case — you describe the extension you want in plain English and receive a production-ready Manifest V3 extension with a real backend and downloadable source code you own. The MV3 compliance requirements are handled automatically. For more on this, see Best Chrome Extension Builders For Non Technical Creators 2026.
Methodology: This article is based on Google's official Manifest V3 migration documentation, the MV2 deprecation timeline, developer case studies published on DEV Community, and publicly available research from the arXiv preprint on Manifest V3 developer experiences. Statistics reflect publicly reported data as of July 2026.
PlugThis writes about Chrome extensions, AI tooling, and the shifting economics of building your own software.
