木曜日の夕方、CapacitorJSのショッピングアプリはAndroid 14ユーザー向けに空白のダッシュボードを表示し始めました。iOSユーザーは通常のブラウジングを続けています。Electronデスクトップユーザーは何も報告していません。オンコールエンジニアはWebViewのバグを想定し、Android Studioを開き、数時間をかけてデバイス間のレンダリング動作を比較しました。最終的な原因はレンダリングのバグではありませんでした。ステージングAPIキーがCDNキャッシュの無効化に失敗したため、モバイルクライアントに到達しなかったからです。
そのインシデントは、リポジトリの境界を尊重しないモバイルの障害がよくあるため、よく知られています。新しいJavaScriptの変更は無害なように思えるかもしれませんが、デプロイ、構成値、パーミッション状態、サービス依存関係、ネットワークパスがユーザーの旅を妨げる可能性があります。マイクロソフトのインシデント分析では 40%の生産インシデントはcodeまたは構成エラーから来ました。60%はインフラ、デプロイ、サービス依存関係から来ました。。 実践的な教訓は単純です。. (アプリのトラブルシューティングは、スタックトレースではなく、全体の障害ドメインから始まる必要があります。)
This playbook follows the workflow I use after shipping CapacitorJS and Electron releases: establish exactly what the user ran, inspect production telemetry before attempting reproduction, verify non-code causes, then debug the narrowest layer that matches the symptom. The seven moves are incident scoping, layered logs, web and native debugging, networking and state checks, CI guardrails, live-update recovery, and a post-incident review that assigns prevention work.
このプレイブックは、CapacitorJSとElectronのリリースを出荷した後使用するワークフローに従っています:ユーザーが実行したものを正確に確定する、生産用のテレメトリを検査する前に再現を試みる、__CAPGO_KEEP_0__以外の原因を検証する、症状に合致する最も狭いレイヤーをデバッグする。この7つの動作は、インシデントスコープ、層化されたログ、Webおよびネイティブデバッグ、ネットワークおよび状態チェック、CIガードレール、ライブアップデートの回復、インシデント後のレビューで、防止の作業を割り当てることです。
- 目次
- 変数を除去して再現する
- Web層とネイティブ層のデバッグ
- ネットワーク、ストレージ、パーミッションのチェックから始める
- 自動テストとCIを早期警戒システムとして使用する
- ライブアップデートを緊急回復チャネルとして使用する
- 次のインシデントを防ぐためにインシデント後の分析を行う
ダッシュボードが暗くなる夜
By Thursday evening, Android users were reporting a blank dashboard while Electron desktop users continued working normally. The first assumption was an Android 14 or WebView regression. That clue narrowed the search, but it did not identify the failure. The affected users also shared a release channel, a cached configuration path, an API environment, and a particular sequence of dashboard requests.
オンコールエンジニアはWebViewのバージョンを比較し始めました。結果は妥当に見えましたが、どこにもつながらませんでした。ダッシュボードが空白になるのはレンダリング例外、空のAPIレスポンス、却下された要求、無効なトークン、機能フラグ、またはセッションの復元を阻害するストレージの読み取りによるものです。codeを変更する前に、影響を受けたユーザーが受け取ったバイナリ、ウェブバンドル、構成、バックエンドパスを確定する必要があります。

失敗の特定
プロダクションのテレメトリから始めましょう。開発用のラップトップではなく。GoogleのAndroidのクラッシュとANRガイドラインでは、イベントをデバイス、オペレーティングシステム、タイムウィンドウで絞り込むことを推奨しています。 失敗の特定ログキャットを使用して、失敗の場所が不明の場合に再現するときは。GoogleのAndroidのビタルのトラブルシューティングガイド)
影響を受けたセッションから次のフィールドをキャプチャしてください:
- ビルドの識別子 ネイティブアプリのバージョン、ビルドID、ウェブバンドルハッシュ、リリースタイムスタンプを記録してください。
- Distribution Channel: ユーザーがキャニバリ、ベータ、ステージング、または安定版のコンテンツを受け取ったかどうかを確認します。
- 実行環境: AndroidまたはiOSバージョン、デバイスモデル、ネットワークタイプ、パーミッション状態、およびアプリがバックグラウンドから再開されたかどうかを記録します。
- 最後の成功アクション: タップシーケンス、リクエスト、レスポンスステータス、表示結果を厳密に保存します。
- 構成スナップショット: APIのベースURL、機能フラグ、認証設定、プラグイン構成を知られている良いデバイスと比較します。
CapacitorはネイティブバージョンとWebView内で実行されているWebコンテンツを分離します。2つのユーザーは、異なるJavaScriptバンドルを受け取ることができるように、ストアでインストールされたバイナリを共有できます。また、異なるネイティブプラグインを使用するように、Webバンドルを共有できます。Electronでは、リリースマニフェスト、メインプロセスバージョン、レンダラーのバンドル、更新チャンネルを含むすべてのチェックが必要です。レンダラーのパッケージメタデータだけでは、ユーザーが実行したものを確立できません。
再現するには変数を削除します。
収集した識別子を使用して、インシデントを次のように分類します。 キャニバリのみ、ステージング、または完全にロールアウト. Canary-only failure points to a specific bundle, flag, or channel assignment. Staged failure suggests audience or device selection logic. Fully rolled-out failure raises the priority of shared configuration, backend behavior, and native compatibility.
Compare the affected device with a known-good one. Check native plugin versions, web hash, channel, API environment, authentication state, and permission grants. Replay the user’s last action sequence locally before using an emulator. If one flag controls the failure, keep other variables constant and bisect that flag’s behavior.
Practical rule: Do not call a reproduction “the same bug” until the build ID, channel, web bundle, operating system, and configuration match.
The Android dashboard incident turned on configuration correction. The team compared snapshots, confirmed that the native binary was valid, and verified that the WebView and dashboard code were unchanged. Production clients were requesting an environment with a staging credential because the earlier cache invalidation had not reached every mobile client. The recovery work therefore focused on correcting the configuration, setting appropriate cache invalidation headers, and verifying the CDN purge from affected regions and client paths.
そのシーケンスは重要な理由がある。成功したパージコマンドは、すべてのユーザーが修正された値を取得できることを証明するものではない。CDNのレスポンス、キャッシュの古さ、バンドルまたは構成ハッシュ、そして新しいクライアントセッションを確認する前に、回復を宣言することは避けるべきである。ネイティブのリビルドは、失敗したアーティファクトを変更せずにロールアウト時間を追加するだけであった。
将来のインシデントに対して同じ規律を守ること: ユーザーのアーティファクトを特定し、失敗の表面を探し、環境の差異を排除し、次にデバッグ code を実行する。。モバイルチームのための書かれた インシデント対応ガイド は、オンコールのランブックに合わせて、テレメトリクエリ、ロールアウトの所有権、パージの検証、そしてネイティブバイナリが失敗したコンポーネントでない場合にライブアップデートを使用する決定を含めるべきである。
Webview、ネイティブ、OSからログを読む
CapacitorJSまたはElectronアプリケーションは、複数のレイヤーで証拠を生成し、各レイヤーは異なる質問に答える。WebviewはJavaScriptの例外と失敗したリクエストを表示するが、プラグインの失敗をすべて説明することはできない。ネイティブログはブリッジとライフサイクル動作を公開し、オペレーティングシステムはメモリの圧力、パーミッションの拒否、プロセスの終了を記録し、アプリケーション code が観察することのないものもある。

症状を証拠と照合する
Webview層 層、コンソールエラー、未処理のPromiseの拒否、ナビゲーションイベント、リクエストURL、レスポンスステータス、リクエストタイミングを収集します。特に、プラグインの静的な拒否は危険です。UIは、カメラ、ファイルシステム、セキュアストレージ、または通知の操作がすでに失敗している場合でも、レンダリングを続けます。
The ネイティブレイヤー ネイティブレイヤーにはAndroidのlogcat出力、iOS os_log レコード、プラグインブリッジのエラー、活動またはビューコントローラーのライフサイクルイベント、ネイティブクラッシュトレースが含まれます。Electronはメインプロセスのログストリーム、自動アップデートイベント、ウィンドウの作成失敗、IPCメッセージを追加します。レンダラーのエラーは必ずしもメインプロセスに出現せず、メインプロセスのクラッシュはレンダラーのコンソール出力に表示されません。
The OSレイヤー OSレイヤーでは、外部のイベントを説明します。メモリの圧力、バックグラウンドの終了、バッテリーの制限、拒否されたパーミッション、プロセスの殺害、システムレベルのクラッシュレポートを探します。このレイヤーは、有用なJavaScriptスタックを持たない「ランダムなクラッシュ」が見られることがよくあります。
関連付ける前にフィルタリングする
共通のリクエストまたはオペレーションIDをWebView、ネイティブブリッジ、バックエンド、中央のログシンクに渡します。ユーザーアクションが始まる前にIDを追加し、ネットワークリクエストとネイティブコールバックを通してIDを保持します。タイムスタンプを一貫した形式で関連付け、デバイスの時計のズレを考慮し、フレームワークのノイズをフィルタリングするのは、元のイベントを保持した後です。
すべてのレイヤーで同じコンテキストフィールドを保存する: アプリバージョン、ウェブバンドルハッシュ、チャネル、デバイス、OS、セッション、機能フラグの状態。集中化された収集により、再現試行はユーザーの証拠と比較できるようになり、仮定に置き換える必要がなくなります。実用的な モバイルデバッグ用のログ分析ツール ウェブレイヤーとネイティブレイヤーのデバッグ
症状を所有するレイヤーをデバッグする。フリーズした画面がネイティブライフサイクルイベントに反応する場合、ウェブビューで始まることが多い。プロセステルミネーション、プラグイン例外、起動失敗はネイティブツールまたはElectronのメインプロセスに属する。レイヤー間を移動するルーティングルールがないと、原因を絞り込むことなく活動が増える。
ウェブビューから始める
Androidの場合、デバッグ可能な__CAPGO_KEEP_0__ビルドをChromeに接続し、
On Android, connect a debuggable Capacitor build to Chrome and open chrome://inspectを呼び出す。 BrowserWindow.webContents.openDevTools() Android
生産スタックトレースは、ソースにマップされる場合にのみ有用です。各ウェブバンドルにソースマップをアップロードして保持し、シンボリケーションアーティファクトが正確なバンドルハッシュと一致することを確認します。重要な操作の場合に制御されたコンソールインテレクターを追加しますが、資格情報、トークン、または個人データをログに記録しないでください。操作名、リクエストID、レスポンスクラス、状態遷移をキャプチャします。

ネイティブツールに移行するには、証拠がそこに指している必要があります。
Android StudioのLogcatをアプリケーションパッケージでフィルタリングし、最小限の可能なアクションシーケンスで再現します。 npx cap run android --livereload WebViewの変更を短縮するために、iterationループを短縮しますが、パッケージされたネイティブアーティファクトを検証しません。iOSでは、Xcodeから実行し、デバイスログのためにデバイスウィンドウを使用します。 InstrumentsのTime Profilerは、継続的なCPU作業に役立ち、 Allocationsはメモリの増加を特定するのに役立ちます。
Electronには2つのデバッグ対象があります。DOM、JavaScript、ネットワークの動作を対象とするRenderer DevToolsを使用します。主プロセスを対象とするDevToolsを使用します。 --inspect または --inspect-brk 主プロセスを対象とするDevToolsを使用します。
ソースマップをアップロードして保持し、シンボリケーションアーティファクトが正確なバンドルハッシュと一致することを確認します。
症状に基づいてルーティングします。UIの動作はWebViewから始まり、ネイティブの終了はAndroid StudioまたはXcodeから始まります。Electronの起動失敗は主プロセスから始まります。 CapacitorのWebViewとネイティブブリッジモデルにおけるこの分割の重要性についての説明が役立ちます。。ブリッジは境界であり、単一のデバッグ画面ではありません。そう扱うことで、各ログ行があなたが持つ質問に答える可能性が高くなります。
ネットワーキング、ストレージ、パーミッションのチェック
チームはAPIを最初にチェックすることが多いです。ネットワークエラーは技術的で馴染みのあるものに見えますが、その習慣は古い状態、パーミッションの宣言変更、またはプラットフォームのアップグレードがサンドボックスの動作を変更したことによる失敗を無視します。失敗ドメインによって最速のチェックが異なります。
| 失敗ドメイン | 共通症状パターン | 最速のチェック |
|---|---|---|
| ネットワーキング | データが空白、ログインループ、タイムアウト、失敗したアップロード、あるネットワークで動作するリクエストが別のネットワークでは動作しない | 実行 curl 同じネットワークから実行し、失敗したWebViewリクエストを検査し、CORSのプリフライト、証明書ピンニング、キャプティブポータル、プロキシの動作を確認 |
| ストレージ | 更新、再起動、またはオペレーティングシステムの変更後、機能が以前は動作していたが失敗する | ストレージのエストイメートをインスペクトし、IndexedDBのクォータエラーをチェックし、暗号化キーの比較を行い、Electronの userData パスを確認し、クリーンなサンドボックスをテスト |
| パーミッション | カメラ、ファイル、通知、ロケーション、またはバックグラウンドの動作が、明確なアプリケーション例外なしで失敗する | iOSの使用説明文をチェックし、Android ACCESS_* の宣言、Electronのパーミッションハンドラー、そして冷スタートのパーミッションタイミング |
ストレージの問題については、 storage.estimate() クォータの圧力を明らかにすることができるが、すべてのデータベースの問題を診断することはできない。クリーンなアプリケーションサンドボックスを手動でクリーンアップし、次に既存のプロファイルと動作を比較する。 Capacitor userData プリファレンスの暗号化キーのローテーションは、以前の有効な値を読み取ることができなくする一方で、SQLiteの書き込み先頭ロギングは、突然の終了後に損傷した状態を残す可能性がある。Electronアプリケーションは、オペレーティングシステムのアップグレードによって解決された
Permissions deserve the same attention. iOS usage descriptions must match the capability being requested. Android permission behavior can drift after SDK changes, and notification prompts can race with cold-start initialization. Electron’s permission handler may reject a request before the renderer receives a useful explanation.
パーミッションは同じ注意を必要とする。iOSの使用説明文は、要求されているキャパシティと一致する必要がある。Androidのパーミッションの動作は、__CAPGO_KEEP_0__の変更後にも変化する可能性があり、通知のプロンプトは冷スタートの初期化と競合する可能性がある。Electronのパーミッションハンドラーは、レンダラーが有用な説明を受け取る前に、リクエストを拒否する可能性がある
ユーザーが「昨日は動いた」と言う場合、ストレージとパーミッションをインスペクトし、ネットワークが変わったと仮定するのではなくてください。
CIは、ユーザーが実行するアーティファクトをテストすることで、最も安価にレグレッションを検出します。開発サーバーに対する緑のテストスイートは、署名されたAndroidパッケージ、iOSアーカイブ、またはElectronインストーラーが起動、バンドルを読み込み、実際の認証済みオペレーションを完了できることを証明するものではありません。
共有ロジックとシェルをテストする
使用する Vitest 共有Webロジックと Jest Electronメインプロセスの動作用に。Capacitor プラグインの場合、JavaScript契約とネイティブ実装を別々にテストし、パーミッションの拒否、利用できないハードウェア、不正なレスポンス、ライフサイクル中断の統合カバレッジを追加してください。
Playwrightは、組み込まれたWebバンドルを実行できます。Electronの場合、Playwright Electronまたは同等のシェルテストを使用して、パッケージされたバイナリに対してテストし、ローカル開発プロセスによって提供されるレンダラーのみでテストしないでください。パッケージテストは、ブラウザテストが隠すミッシングアセット、不正なパス、署名ミス、起動アサムションを検出できます。
デバイスカバレッジは、実際のインストールベースを反映する必要があります。BrowserStackまたはSauce Labsを使用して、意図的に選択されたデバイスプロファイル、オペレーティングシステム、パーミッション状態、ネットワーク条件をテストできます。目標は、最大の行列サイズではなく、代表的な失敗カバレッジです。
失敗をマージブロックする
明示的なチェックを追加する
- バンドル変更: 不正のバンドルサイズの差分とソースマップの欠如を拒否する。
- ネイティブの配置: プラグインのバージョン遅れと不互換な
minSdkVersion設定を検出する。 - アーティファクトの整合性: 署名、パッケージの識別、埋め込まれたアセット、リリースマニフェストを検証する。
- 起動の動作: パッケージされたアプリを起動し、認証済みのエンドポイント要求を完了する。
- 更新の動作: 古いバンドルをインストールし、候補の更新を適用し、再起動し、ロールバックの動作を確認する。
1 つの GitHub のステータスチェックを通じて、赤い信号がマージをブロックするように、すべての結果を公開する。完全にパスしたユニットテストを持つビルドが署名されたアーティファクトの検証に失敗した場合、失敗として扱う。 'ほぼ緑' と見なすのではなく。
The 継続的インテグレーションのセットアップは、Capacitor リリース用の これらのチェックを繰り返しパイプラインに組み込むことが便利です。CI は、生産性の向上に役立つものではありませんが、ステージングに到達する欠陥の数を減らし、インシデントの際にオンコールエンジニアが扱う不明な要素を減らすことができます。
ライブアップデートを緊急回復チャネルとして活用する
生産性の低下は常に新しいネイティブビルドが必要ではない場合があります。JavaScript、CSS、コピー、構成、または他のWebアセットに欠陥がある場合、ライブアップデートはユーザー体験を回復させ、チームが適切なリリースを準備するまで待つ必要があります。そのため、ライブアップデートの配信は 運用回復チャネル、ではなく、単に外観の変更のための便宜的なものではありません。
安全性の要件は、制御です。カニラ、ベータ、安定したアウディエンス用に別々の名前付きチャネルを維持し、ネイティブアプリIDと互換性のあるランタイム制約を明示し、各アウディエンスが受け取るバンドルの記録を残すことが重要です。ライブアップデートはネイティブの許可を追加することはできず、ネイティブのプラグインを置き換えることはできず、Electronのメインプロセスを変更することはできず、初期化が完了する前に失敗したものを修復することはできません。そのようなケースは、ストアまたはインストーラー リリースが必要です。

ガード付きのロールアウトを使用する
緊急フローは次のようになります:
- 確認範囲を確定する 影響を受けるネイティブバージョン、チャネル、バンドルハッシュ、失敗信号を特定する
- 最小のパッチを用意する: 失敗するパスを修復するために必要なウェブの動作のみを変更する。
- ターゲットとなるカニアードアーディエンスを設定する: 失敗するパスを修復するために必要なウェブの動作のみを変更する。
- トラブルシューティングのためのデータを収集する: クラッシュ、ロード、リクエスト、更新の失敗のシグナルを対象のコホートと比較する。
- プロモーションまたはロールバック: シグナルが健康である限り、拡大する。新しい失敗を導入したパッチがロールバックされるように、直ちにロールバックする。
ロールバックは、アップデータが失敗を検出でき、前のバンドルが利用可能な場合にのみ、ユーザーを保護する。バージョン履歴とチャンネルガードレールを維持することで、サポートが特定のデバイスの問題を説明できるようにする。
Capgoは、CapacitorJSおよびElectronアプリケーション向けに署名されたウェブバンドル配信、ターゲットチャンネル、デバイスごとのログ、採用率と失敗率のメトリック、バージョン履歴、自動ロールバック保護を提供します。実際の決定ルールは直接的です。 ウェブバンドルの修正がウェブバンドルに限定され、アップデータが安全に開始できる場合、ライブアップデートを使用します。ランタイム、プラグイン、パーミッション、パッケージ、またはメインプロセスが関与している場合、ネイティブホットフィックスをスケジュールする。. Capacitor ライブアップデートフロー __CAPGO_KEEP_0__ ライブアップデートフローは、2 つのパス間の境界を説明します。
インシデント後の分析が次のインシデントを防ぐ
リトロスペクティブは、システムを変更することでその位置を獲得します。ログ、デプロイメントコンテキスト、オペレーターの決定が利用可能なときに書きましょう。記録は事実、非難のない、そして、もう一度インシデントを再構築することなく、もう一度エンジニアが欠けているガードレールを特定できるようにするための十分な情報を含めましょう。
5 つの具体的なブロックを使用します。
タイムラインにタイムスタンプのテレメトリを記録します。 最初の失敗したリクエスト、影響を受けたリリース、警告の作成、調査ステップ、対策、回復を記録します。Android ダッシュボード インシデントの場合、タイムラインは、iOS が有効なレスポンスを受け続けていたのに対し、構成ロールアウト後に空白のビューが表示されたことを示すかもしれません。
ユーザーに視覚化された障害モード。 顧客が経験したことを説明するのではなく、code が何をしたかを説明しないでください。 “Android ユーザーは、認証後に空白のダッシュボードを表示しました” は、レスポンダーに方向性を与えるのではなく、「API キー不一致」はそうではありません。最初の説明は、破壊された旅程と、検出しなければならない信号を指します。
検出のギャップ。 チームが遅れて学んだ理由を述べます。クラッシュモニタリングは、成功したアプリのレンダリングが緑色のままだったかもしれませんが、認証済みのリクエストの失敗や空白のダッシュボード ペイロードの警告が追跡されていなかったため、記録された欠けている信号と、そこで発生しなければならない信号を記録します。
code以外の要因の寄与 リスト内の設定のずれ、キャッシュの動作、デプロイのタイミング、サービス依存関係、権限の変更、またはElectronの自動更新の競合。これらのドメインは、エラーがアプリケーションcodeにない場合でも、生産性の低下が発生する可能性があるため、早期のチェックが必要です。
予防的なガードレール。 問題を発見したテストまたはコントロールを割り当てます。例として、デプロイ時に生産環境のクレデンシャルを検証する、代表的なクライアントから配信された構成を確認する、またはパッケージ化されたElectronの起動テストを追加するなどです。ガードレールには、単にリトロスペクティブに記述された文だけではなく、オーナーと失敗条件が必要です。
通知パスは同じレビューに含まれます。チームにメールアラートが届かない場合は、Gmailでメールをスパムから防ぐ方法についての実用的なリソースを参照してください。 通知チェック中にメールアラートの送信が成功しても、オペレーターがメッセージを受け取ったことを証明するものではありません。 インシデントを閉じる前に、作業を割り当てます。
各ブロックに、オーナー、期限、検証方法を1つずつ割り当てます。24時間以内にインシデントを再度レビューしてください。
24時間 エンジニアは、調査から仮定を挑戦することができます。新しいテスト、ダッシュボード、構成チェック、またはロールアウトルールが正常に実行された後のみ、アイテムを閉じます。この最終チェックリストを使用します。
正しいネイティブビルドとWebバンドルを特定しましたか?
- 予防的なガードレール。
- Capgoでは、code、構成、展開、インフラストラクチャ、および依存関係の原因を区別しましたか?
- テレメトリは、ユーザーに表示されるエラーだけでなく、クラッシュも表示しましたか?
- 影響を受けたチャネルと知られている良いチャネルをテストしましたか?
- 生産前に失敗するガードレールを追加しましたか?
- ライブアップデートまたはネイティブリリースが適切だったかどうか、ドキュメントに記載しましたか?
- 1人の所有者が修正を確認しましたか?
ユーザーの苦情は、レビューがクラッシュのみをカバーする必要があることを示しています。6,634アプリの検査の結果、 支払い失敗がアプリデバイスの互換性 28.6% UIとUXの摩擦 28.4%サブスクリプションの問題 25.4%payment failures affected of apps, device compatibility , UI and UX friction , subscription trouble 21.8%, ログインエラー 17.2%, ながらクラッシュは7位でした 10.3%. (モバイルアプリの不満を調査したBright App Data) アプリがクラッシュした理由を「なぜアプリがクラッシュしたのか?」とだけ尋ねるトラブルシューティングプロセスは、支払い、サインイン、または通常の製品使用ができなくなる障壁を無視する可能性があります。
安定性データは同じ運用モデルを裏付けています。ベンチマークでは、メディアンアプリは 99.95%のクラッシュフリーのセッション, トップパフォーマンスアプリは 99.99% , 弱いアプリは 99.77%以下。 また、メディアン ANR率は10,000セッションあたり2.62, である 10万回のセッションあたりのOOMレートは1.12、およびアプリハングレートは 64から103までの10万回のセッションあたり 品質レベルに応じて。(モバイル安定性ベンチマーク
) 高い安定性でも、意味のあるエラーが残っている。チームは、失敗したリクエスト、空白の状態、ハング、更新エラー、ユーザー向けの症状など、テレメトリを必要とする。 2026年の報告書によると、ユーザーは基本的な機能が壊れたことについて6倍多く苦情を寄せた 新機能のリクエストよりも. (、報告書によると1回のクラッシュ後、15.4%のユーザーがアンインストールし、2-3回のクラッシュ後、半分以上が放棄した
使用 Capgo Capgoにプルリクエストを送信する