ブラウザ拡張機能で生じる「Service worker registration failed. Status code: 15」エラーの解決方法
ブラウザ拡張機能の開発中にService Workerの登録で「Status code: 15」エラーが発生した際の原因調査と解決方法について共有します。
エラーの概要
発生したエラー
Service worker registration failed. Status code: 15
発生環境
- Plasmoフレームワークを使用したブラウザ拡張機能(Chrome)
pnpm dev
実行時にエラーが発生- 拡張機能のbackground scriptが正常に動作しない状態
- Service Workerのビューを検証できない状態

エラーの原因分析
Status code: 15の意味
Status code: 15は、Service Worker環境で利用できないAPIを使用した際のスクリプト評価エラーです。
Service Worker環境の制限
Service Worker環境では以下のAPIが利用できません:
window
オブジェクトdocument
オブジェクトlocalStorage
/sessionStorage
- DOM関連のAPI全般
alert()
/confirm()
/prompt()
- 同期的なXMLHttpRequest
これらの制限については、以下の公式ドキュメントで詳しく説明されています:
エラーの一般的な原因
典型的なケース:
- ストレージAPIの使用 -
localStorage
やsessionStorage
への直接アクセス - DOM APIの使用 -
document
やwindow
オブジェクトの参照 - UI関連APIの使用 -
alert()
、confirm()
などの呼び出し - 同期的なネットワークAPI - 同期的なXMLHttpRequestの使用
今回の例:localStorageが原因だったケース
今回の例では、i18n処理で開発環境用にlocalStorage
を使用していた関数を、意図せずbackground scriptでimportしていたことが原因でした。
background script → モジュールのインポート → 初期化処理 → localStorage.getItem() → エラー発生
一般的な解決アプローチ
1. 環境判定による条件分岐
Service Worker環境かどうかを判定し、使用するAPIを切り替える方法:
// Service Worker環境の判定const isServiceWorker = typeof globalThis !== 'undefined' && typeof window === 'undefined'
if (isServiceWorker) { // Service Worker対応のAPIを使用 // 例: chrome.storage.local} else { // 通常のブラウザAPIを使用 // 例: localStorage}
2. try-catchによるエラーハンドリング
環境判定が難しい場合は、エラーをキャッチして代替処理を行う:
try { // ブラウザAPIの使用を試みる const value = localStorage.getItem('key')} catch (e) { // Service Worker環境では例外が発生するため、代替処理を実行 console.warn('API not available in Service Worker:', e)}
3. ブラウザ拡張機能APIへの移行
Service Workerでも使用可能なAPIに完全に移行する方法:
通常のAPI | Service Worker対応API |
---|---|
localStorage | browser.storage.local / chrome.storage.local |
sessionStorage | browser.storage.session / chrome.storage.session |
XMLHttpRequest (同期) | fetch() API |
window.location | browser.tabs.query() / chrome.tabs.query() |
※ browser.*
APIはFirefox、chrome.*
APIはChrome/Edgeで使用。両方に対応する場合はポリフィルの使用を検討してください。
エラー調査の手順
1. エラーメッセージの確認
chrome://extensions
でエラーの詳細を確認します。
2. 使用禁止APIの特定
以下の手順で問題のあるAPIを特定します:
# Service Workerで使用できない主要なAPIを検索grep -r "localStorage\|sessionStorage\|document\.\|window\." src/
# DOM操作系のAPIを検索grep -r "getElementById\|querySelector\|alert\|confirm" src/
3. インポートチェーンの追跡
background scriptから始まるインポートチェーンを追跡し、どこで問題のAPIが呼ばれているかを特定:
- background scriptのエントリーポイントを確認
- importされているモジュールを順次確認
- モジュールのトップレベルで実行されるコードに注目
- 初期化処理や定数定義で使用されているAPIをチェック
調査すべきポイント
「Status code: 15」エラーが発生した場合は、以下のポイントを順番に調査することで原因を特定できます:
1. モジュールのトップレベルコードを確認
モジュールのトップレベルで実行されるコードが原因の大半です:
- 定数や変数の初期化処理
- グローバルスコープでの関数呼び出し
- クラスの静的プロパティの初期化
2. よくある問題パターン
// ❌ これらはすべてエラーの原因になりますconst theme = localStorage.getItem('theme') // トップレベルでのlocalStorageconst lang = document.documentElement.lang // トップレベルでのDOM参照const width = window.innerWidth // トップレベルでのwindow参照
3. デバッグのコツ
3-1. 二分探索でエラー箇所を特定
- importを一時的にコメントアウトして範囲を絞る
- エラーが消えたら、そのimportが原因
3-2. console.logでの確認
console.log('Module A loaded') // 各モジュールの先頭に配置
3-3. 条件付きインポート
// Service Workerでは実行されないようにするif (typeof window !== 'undefined') { import('./browser-only-module')}
まとめ
「Service worker registration failed. Status code: 15」エラーは、Service Worker環境で使用できないAPIにアクセスした際に発生します。
エラー解決の手順:
- モジュールのトップレベルコードを最初に確認
- localStorage、window、documentなどの使用箇所を検索
- インポートチェーンを辿って問題の発生源を特定
- 環境判定またはブラウザ拡張機能 APIへの置き換えで解決
Service Workerの制限を理解し、適切なAPIを選択することが重要です。