5 月 19 日に Android の壁紙アプリ v2.1.1 のホットフィックスをほぼ書き終えたあと、Crashlytics を眺めながらコーヒーを淹れていたら、Play Vitals の「ユーザー認識クラッシュ発生率」が 1.08% に上がっていました。Google の「不正な動作」フラグが立つしきい値が 1.09% なので、あと 0.01%。
壁紙系の主力 2 本(綺麗な壁紙・浮世絵壁紙)は、この 5 月にメジャーアップデート(v2.0.0 / v1.7.0)を投げたばかりでした。リリース直後の Crashlytics は新規バグの祭りです。11 日間で 30 件以上のスタックトレースを掘り、そのうち 13 件を確定でコードに落とし、6 件を OS・SDK 起因として塩漬け判定にしました。個人開発なので、仕分けも実装もリリース可否の判断も同じ一人がやります。この記事はその工程を、Claude Code の使い方を中心にして公開する実装ログです。
「個人開発で Crashlytics を毎日チェックする習慣はあるけれど、スタックトレースを読みきれずに『そのうち直す』が溜まっている」「Play Vitals のしきい値接触で焦って手当てしたら別の不具合を出した」あたりで困っている方を想定読者に置いています。
11 日間の地図 — 何を直して、何を直さなかったか
最初に全体像を出しておきます。期間は v2.1.0 リリース後の観察期から、v2.1.1 / v1.8.1 を Play Console に投げた 5 月 27 日まで。
5/12 (Day 1) : v2.0.0 リリース直後の Crashlytics 新規 issue 12 件を仕分け。RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline の IOOBE が 28 日で 50+ ユーザーまで急増していたのを発見
5/13 (Day 2) : Android 6.0.1 ユーザー全員が起動 3 秒でクラッシュする j.u.function.Supplier NoClassDefFoundError を発見・即日修正。coreLibraryDesugaringEnabled を有効化するだけの 1 行修正
5/13 (Day 2 後半) : Gallery.onResume の入れ子構造で、戻る時のインタースティシャル広告がリワード誘導に勝てない論理を解体
5/14〜18 (Day 3〜7) : v2.1.0 をリリース、観察期。BW-015 (PageJumpSlider の NPE) が 1 user → 9 user に伸張。BW-009 (R8 strict mode + density split で drawable がストリップされる) が継続発生
5/19 (Day 8) : 上の 1.08% スパイクが見えた日。ViewPager2 内部 RecyclerView の fling 中 IOOBE (BW-017) を setItemAnimator(null) + setHasFixedSize(true) の 2 行で潰し、Glide プレースホルダーの同期デコード ANR (BW-027) を ColorDrawable 置換で潰す
5/22 (Day 11) : API 37 エミュレーターで Material You が overlay を再生成して CategoryActivity が真っ白になる無音 UX バグを再現・修正
5/25 (Day 14) : Play Console + Crashlytics を全件再精査。残存リスクの BW-015 / UE-007 / BW-009 を v2.1.1 / v1.8.1 で塩漬け撤回・先行リリース確定
5/27 (Today) : v2.1.1 / v1.8.1 を Play Console に審査提出
この期間、Claude Code のセッションは合計 27 回起動しました。1 回あたりだいたい 30 分〜2 時間。コードの実装と Crashlytics の確認、両方を 1 つのセッションに混ぜないのが安定運用のコツだったので、後述します。
スタックトレースを Claude Code に投げる時の前処理
Crashlytics や Play Console の「クラッシュの問題」ページからスタックトレースをコピーすると、ほぼ毎回 200〜400 行になります。これを生のまま貼ると Claude Code のコンテキストを浪費する上に、原因仮説が曖昧になりがちです。私は次の形に整形してから投げる癖をつけました。
## 環境
- アプリ: 綺麗な壁紙 v2.1.0 (vc=49)
- 端末: Sharp AQUOS wish4 (DOCOMO SH-52E)
- OS: Android 15 (SDK 35)
- 発生: 7日で 117 events / 99 users(74.4% 寄与)
## トップ 5 フレーム(関係ありそうな上位だけ抜粋)
RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline (line 7160)
LinearLayoutManager.scrollBy
RecyclerView.scrollHorizontallyBy
RecyclerView.scrollStep
RecyclerView$ViewFlinger.run
## メッセージ
Inconsistency detected. Invalid item position 1(offset:1).state:1030
## 既知パターン早見表での当該行
- "ViewPager2 内部 RV の fling 中"
- 修正候補: setItemAnimator(null), setHasFixedSize(true), Predictive Animation を切る
## 実装側に予想がついている部分
ThumbnailActivity の ViewPager2 で setAdapter 直後に
mViewPager.getChildAt(0) で内部 RecyclerView を取って
チューニングを当てれば直りそう。Gallery 側にも予防的に当てたい。
Claude Code に投げる前に、自分なりの仮説と「どのファイルを触りたいか」を 3 行でも書いておくと、出力が一気にコードに寄ります。なにも書かずに丸投げすると、解説 8 割・コード 2 割の応答になりがちで、それは個人開発の保守フェーズでは欲しい形ではありません。
このスタックトレースを Claude Code にこのまま貼ると、ほぼ確実に次のような修正案を返してきます。
// ThumbnailActivity#ThumbnailPager.start() に追加
mViewPager. setAdapter (mAdapter);
View inner = mViewPager. getChildAt ( 0 );
if (inner instanceof RecyclerView) {
RecyclerView rv = (RecyclerView) inner;
rv. setItemAnimator ( null ); // Predictive Animation 由来の状態不整合を抑制
rv. setHasFixedSize ( true ); // ノートブック型再計測のスキップ
}
これは v2.1.0 → v2.1.1 で実際に入れた修正そのままです。修正前は 7 日で 117 events / 99 users、修正後は v2.1.1 リリース後の観察対象として「>99% 帯への改善見込み」と判定しました(クラッシュフリーユーザー 97.98% からの引き上げ)。
setItemAnimator(null) は副作用があります。私の場合、PageJumpSlider のドラッグで setCurrentItem(largePosition, false) を呼んだ時に LayoutManager の再 layout がスキップされて壁紙が変わらないバグ(BW-032)を別途踏みました。Claude Code に「setItemAnimator(null) で何が変わるか、ViewPager2 の挙動に副作用がないか教えて」と聞いておくと、こういう罠を事前に拾えます。
既知バグトラッカーを「Claude が読める形」で保持する
私は known-bugs-tracker.md というファイルを 1 つのアプリにつき 1 本持っています。中身は単純なマークダウンですが、Claude Code が読んだ時に最速で当該バグを引き当てられる構造に整えてあります。
### v2.1.0(公開中、vc=49)の既知バグ
| ID | バグ内容 | スタックトレース起点 | ステータス | 影響規模 | 修正先 |
|---|---|---|---|---|---|
| BW-017 | RecyclerView IOOBE(fling 中) | `RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline` → `RecyclerView$ViewFlinger.run` | 緑(v2.1.1 で修正) | 7日で 117 events / 99 users、v2.1.0 のみ 74.4% | setItemAnimator(null) + setHasFixedSize(true) |
| BW-027 | Glide プレースホルダーが同期デコード ANR | `libhwui ImageDecoder_nDecodeBitmap` → `Glide.SingleRequest.getPlaceholderDrawable` | 緑(v2.1.1 で修正) | 7日で 1 event / 1 user / Sharp AQUOS SX4 | R.drawable.background_silver(220KB JPG)を XML ColorDrawable に置換 |
この表のあとに「既知パターン早見表」というセクションを持っています。Crashlytics のタイトル文字列を 1 行マッピングしただけのものです。
| 文字列(Crashlytics タイトル) | 該当 ID | 備考 |
|---|---|---|
| `RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline` IOOBE | BW-002 / BW-007 / BW-017 / UE-004 / UE-009 | ViewPager2 内部 RV の fling 中。v2.1.1 / v1.8.1 で `setItemAnimator(null)` 適用済 |
| `Glide.SingleRequest.getPlaceholderDrawable` + ANR | BW-027 / UE-016 | JPG プレースホルダーの同期デコード。v2.1.1 / v1.8.1 で XML ColorDrawable に置換 |
| `[libart.so] art::DumpNativeStack` ANR | UE-013 | ART ランタイム自身のスタックダンプ中。低 DAU 統計ノイズ |
新しい Crashlytics 通知が来たら、まずこの早見表をテキスト検索します。ヒットすれば既知。ヒットしなければ Claude Code を起動して仮説生成 → 該当行を追記、というループです。11 日間で 30 件のうち、約半数はこの早見表に既知としてマッチしました。残り半分のうち、自分のコードで直せるのは更にその半分、残りは OS や SDK 内部の問題で塩漬け判定 — このざっくり 4 分割を見えるようにしておくと、毎朝の Crashlytics チェックが 5 分で終わるようになります。
「個人で直せないバグ」を堂々と塩漬けにするための区分
11 日間で Crashlytics に出てきたバグのうち、6 件は私の側のコードでは絶対に直せない種類のものでした。Play Console と Crashlytics の両方で「新規」フラグが立つので、放置すると毎朝の確認のたびにストレスが溜まります。これらを最初から「対応不可」として分類できる根拠を、Claude Code に整理してもらった結果が下記です。
LinkedHashMap$LinkedHashIterator.nextNode + zzbiv (play-services-ads 25.2.0) — Google Mobile Ads SDK 25.x 内部の並行アクセスバグ。私の側で並行性を気にしても何も変わらない。SDK 更新待ち
com.applovin.impl.p.onCreate NPE / com.applovin.impl.g0.a NPE — AppLovin SDK 内部の null 参照。難読化されていてアプリ側で防げない。SDK 更新を待つしかない
Parcel.readFloatArray "bad array lengths" — OS の WindowManager IPC バグ。アプリ側からの介入は不能
GoogleCertificatesRslt SecurityException — Google Play Services が apk 署名を検証できない端末(GMS なし/root/サードパーティストア配布等)。改造 APK の可能性も高い
[libc.so] __ioctl ANR + 「バインダー呼び出しが遅い」タグ — Sharp AQUOS の特定機種でディスプレイ HAL レイテンシが原因のシステム側 ANR。OS 側の問題
BaseDexClassLoader.findClass com.rini.xanrn.Wish — 改造 APK/マルウェアラッパー。正規ストア経由ユーザーへの影響なし
ここで重要なのは「直さない判断」を Claude Code に書いてもらって、known-bugs-tracker.md に証拠と一緒に残すことです。次に同じスタックトレースが出てきた時、過去の自分が「これは SDK 待ちです」と書いた行を読めば、3 秒で判定が終わります。known-bugs-tracker.md の「ステータス凡例」に「対応不可(外部要因)」というステータスを最初から用意しておくと、塩漬け判定が運用に乗ります。
「対応不可」に落とす判定は感覚でやるとぶれるので、三つの条件のどれに当たるかだけを見るようにしました。スタックトレースの上から下まで自分のパッケージ名が一度も出てこないこと。同じ signature が別アプリ・別バージョンでもほぼ同じ比率で出ていること。SDK か OS のバージョンで層別すると特定の一群に固まること。三つのどれにも当たらないなら、それはたぶん自分のコードの問題です。SDK 内部の null 参照に時間を投じても、自分が触れる範囲は一行も良くなりません。
Play Vitals のしきい値接触で何を入れ、何を見送ったか
5/19 に上述の 1.08% を見て、当初は塩漬け予定だった v2.1.1 を「7 月の targetSdk 37 移行と一緒にまとめてリリース」する方針を撤回しました。release-plan-v2.1.1-v1.8.1.md というファイルを Claude Code に作ってもらって、何を v2.1.1 に入れて何を入れないか、優先度順に並べました。
v2.1.1 に入れた修正は以下 7 件です。
BW-017 / UE-009 — ViewPager2 内部 RecyclerView の fling 中 IOOBE。setItemAnimator(null) + setHasFixedSize(true) を ThumbnailActivity と Gallery の 2 箇所に予防的に適用
BW-027 / UE-016 — Glide プレースホルダーの同期デコード ANR。R.drawable.background_silver(220KB JPG)を XML ColorDrawable R.drawable.background_silver_placeholder に差し替え。Glide listener / .into() を try-catch で包み、placeholder 起因の二次クラッシュも防御
BW-015 / UE-007 — PageJumpSlider.hide() のアニメーション完了時 NPE。onAnimationEnd で mContainer != null チェックを追加
BW-009 / UE-021 — R8 strict mode + density split で background_silver.jpg がストリップされる。res/raw/keep.xml に tools:keep="@drawable/background_silver,@drawable/background_silver_placeholder" を追加
BW-030 / UE-017 — API 37 / Android 14+ で Material You が overlay を再生成し、CategoryActivity が真っ白になる無音 UX バグ。imageList が empty かつ復元不能と判定したら finish() して ThumbnailActivity に戻す graceful finish
UE-015 — WallpaperPagerAdapter.onBindViewHolder で mCurrentHolder = holder を直接代入していたため、オフスクリーン先読み bind で隣ページに上書きされ、「壁紙に設定」で 1 つズレた壁紙が設定されるユーザー報告バグ。mCurrentHolder の更新を onPageSelected → setCurrentHolder() に一本化
Liftoff (Vungle) 早期 reward 不具合への防御線 — AdMobRewardedAd / AdMobRewardedIntersAd に MIN_WATCH_DURATION_MS = 3_000L ガードを追加。3 秒未満の reward callback を Suspicious reward callback after only NNms でログ出力 + 付与スキップ
逆に v2.1.1 で見送ったものを挙げると次の通りです。「Crashlytics に出ているが直すと別の事を壊しそうなもの」と「targetSdk 37 移行とセットでないと意味がないもの」が中心です。
BW-003 / BW-023 — 起動時の MessageQueue ANR。広告 SDK 初期化の非同期化が必要で、ホットフィックスでやると別の事を壊すリスクが高い。v2.2.0 に繰り越し
BW-005 — Mintegral SDK のロック競合 ANR。SDK 更新を待つほうが安全
BW-016 / BW-019 — 1 user / 1 event の散発。蓄積を待ってから判断
「ホットフィックスにつめこみすぎない」「正規リリースに繰り越せるものは繰り越す」という線引きを、Claude Code に「このリストを優先度別に分けて、入れる / 見送る理由を添えて」とお願いして整理しました。一人で書いていると優先度判断にバイアスが入りやすいので、第三者視点の整理は有効です。
ANR 系は ANR 系で別ループにする
Crashlytics で扱いが一番難しいのが ANR です。スタックトレースが native 寄りで、art_jni_trampoline や libhwui などのフレームが大量に出てきて、コードの当事者性が見えづらい。クラッシュ系と一緒に処理しようとすると判定基準がぶれます。
私は ANR 専用に「ループ A → 端末 / OS 情報を見る、ループ B → main thread が何で止まっているかを見る、ループ C → SDK 初期化の同期処理を疑う」の 3 段階に分けて、Claude Code に投げる時もこの 3 段階を明示するようにしています。例えば BW-027 の同期デコード ANR は次のような問い方をしました。
Sharp AQUOS SX4 / Android 15 で WallpaperPagerAdapter.onBindViewHolder:145 のあとに Glide.SingleRequest.getPlaceholderDrawable を経由して libhwui ImageDecoder_nDecodeBitmap+512 に降りていく ANR が 1 件出ています。main thread で 220KB の JPG を ImageDecoder で同期デコードしているのが原因の可能性が高いと考えています。Glide の placeholder に R.drawable.background_silver (220KB JPG) を渡しているのですが、これを軽量な XML ColorDrawable に置き換えるべきでしょうか。XML ColorDrawable は ImageDecoder を経由しないという理解で合っていますか。
Claude Code は「ColorDrawable は ImageDecoder を経由せず、内部で android.graphics.drawable.ColorDrawable として直接解決される」「JPG の場合は density に応じた resampling と decode が走るため、低 DAU 端末でも main thread に余計な負荷がかかる」と教えてくれました。これで XML ColorDrawable 置換に踏み切れました。
ANR を扱う時のコツは「main thread で何が起きているか」を 1 行に圧縮する作業を最初にやることです。art_jni_trampoline の下に IPackageManager$Stub$Proxy.getNameForUid+252 があれば「system_server とのバインダー IPC でブロック」「Display.getRefreshRate を経由していたらディスプレイ HAL レイテンシの可能性」のように、文章 1 行に落としてから Claude に投げると、SDK 起因か OS 起因かの切り分けが早いです。
Claude Code に「実装してもらう」のではなく「議事録を取ってもらう」
11 日間でセッションを 27 回起動して気づいたのは、「コードを書かせる」より「自分の判断を整理して書き残させる」用途で Claude Code を使うほうが、保守フェーズでは効きました。
具体的には、デバッグの最中に次のような節目があります。
「BW-017 を setItemAnimator(null) で潰すと決めた。副作用として PageJumpSlider のドラッグが効かなくなる可能性があるので、setHasFixedSize(true) も同時に当てる」
「BW-009 が v2.1.0 リリース後も残った。drawable-nodpi に置いただけでは density split で R8 が誤除去するパターンの可能性が高いので、res/raw/keep.xml を追加する」
「BW-030 は API 37 エミュレーターでだけ再現する。configChanges に assetsPaths を足すという選択肢もあったが、API 互換性リスクが高いので graceful finish で対処」
これを口頭で Claude Code に説明して、「いま話したことを、known-bugs-tracker.md の BW-XXX の 修正先 列に入れる形で短くまとめて」と頼みます。Claude Code は議事録の整理が得意なので、運用ノートが Crashlytics の証拠と一緒に残ります。半年後に同じスタックトレースを見た時に「過去の自分はこう判断した」が読めることが、個人開発の保守では何よりの資産になります。
議事録として効いたのは、結論よりも「採らなかった選択肢」を残しておくことでした。BW-030 で configChanges に assetsPaths を足す案を捨てた理由が一行あるだけで、半年後の自分が同じ検討をゼロからやり直さずに済みます。採用した修正は差分を読めば分かりますが、捨てた案はどこにも残りません。
運用に乗ったあとに見えてきた指標
11 日間のループを抜けて v2.1.1 / v1.8.1 を審査に投げたあと、Crashlytics と Play Console の指標は次のように動きました(2026-05-25 時点)。
BW v2.1.0 7日 : クラッシュなしユーザー 98.62%(+0.48%) 、クラッシュ 67 件 / ユーザー 57 名(前週比 -42.7% / -43.6%)
BW v2.1.0 Play Console 28日 : 15 件、全部既知。上位 4 件(BW-017 / BW-015 / BW-027 / RecyclerView IOOBE 変種)は v2.1.1 で修正済み
UE v1.8.0 7日 : 7 件、全部既知。新規未知バグはゼロ
クラッシュフリー率 +0.48% は地味な数字に見えますが、実数ではクラッシュ 67 件 / ユーザー 57 名、前週比 -42.7% / -43.6% です。setItemAnimator(null) + setHasFixedSize(true) という 2 行と、XML ColorDrawable への置き換え。動いたのはそれだけで、比率にすると 4 割強が消えました。個人開発のホットフィックスでも、Crashlytics の指標を一つひとつ抑えに行くと、ユーザー数ベースのインパクトは想像より大きい印象です。
「もう出ていない」を証拠にするまでの日数を先に計算する
v2.1.1 を審査に投げた翌日、Crashlytics のダッシュボードで新バージョンのクラッシュフリー率が 100% と出ていて、一瞬だけ気分が良くなりました。採用率を見ると、その時点で v2.1.1 が入っていたのは全体の数パーセントです。母数が小さければ、何も直っていなくても 100% は普通に出ます。
以前の私はここで known-bugs-tracker.md のステータスを緑(修正済み)に塗っていました。そして数週間後に同じ signature が戻ってきて、緑を剥がすところからやり直す。二度ほどそれを繰り返してから、「緑に塗ってよい日」を先に計算する運用に変えました。
計算自体は単純です。修正前のバージョンで、7 日間に当該バグへ当たったユーザーが k 人いたとします。修正後に同じ規模の母数を観測して 0 件が続いたとき、それが偶然でないと 95% の水準で言えるまでの日数は次の形になります。
#!/usr/bin/env python3
"""fix-confidence.py — 「もう出ていない」が証拠になるまでの観測日数。"""
import math
def observation_days (k: float , adoption: float = 1.0 , confidence: float = 0.95 ) -> float :
"""k: 修正前 7 日間の影響ユーザー数 / adoption: 新バージョンの採用率"""
if k <= 0 or not 0 < adoption <= 1 :
raise ValueError ( "k > 0 and 0 < adoption <= 1" )
return - 7.0 * math.log( 1 - confidence) / k / adoption
if __name__ == "__main__" :
print ( f " { 'k' :>5 } { '100%' :>8 } { '20%' :>8 } { '5%' :>8 } " )
for k in ( 99 , 20 , 9 , 1 ):
row = [observation_days(k, a) for a in ( 1.0 , 0.2 , 0.05 )]
print ( f " { k :>5 } " + " " .join( f " { d :>8.1f } " for d in row))
手元で走らせた出力がこちらです(単位は日)。
k(修正前 7 日の影響ユーザー数) 採用率 100% 採用率 20% 採用率 5%
99 0.2 1.1 4.2
20 1.0 5.2 21.0
9 2.3 11.7 46.6
1 21.0 104.9 419.4
この式で目を引くのは、母数(そのバージョンの 7 日アクティブユーザー数)が答えに出てこないことです。修正前後で母数が変わらなければ約分で消えます。厳密式(ln(1-C) / ln(1-k/母数))に母数 2,000 / 5,000 / 20,000 / 100,000 を入れて突き合わせたところ、いずれも 21÷k 日に一致しました。必要なのは Crashlytics の issue ページに出ている影響ユーザー数だけで、DAU を別途持ってこなくても観察期限が引けます。
実際の判定に当てると、11 日間で扱ったバグの性格がはっきり分かれました。
BW-017 (7 日で 99 ユーザー)— 全面採用なら 5 時間、採用率 20% でも 1 日強。リリース翌々日には緑に塗ってよい
BW-015 (1 user → 9 user に伸張)— 採用率 20% で約 12 日。次の正規リリースまでは観察中のまま置く
BW-027 (7 日で 1 event / 1 user)— 全面採用でも 21 日、採用率 20% なら 105 日。観測では直ったと言えない
三つ目が厄介でした。BW-027 の修正(220KB の JPG プレースホルダーを XML ColorDrawable へ置換)は、機序としては明確に正しい。main thread の ImageDecoder を経由しなくなるので、原因側が消えています。それでも「出なくなったこと」を数字で示すには、次のメジャーアップデートまで待たされる。ここで緑に塗ってしまうと、根拠の質が違うものが同じ色で並びます。
本文前半で引いた tracker の抜粋では BW-027 も緑のままですが、あれは当時のスナップショットです。いまはステータス凡例を三段に分けて、あの行は青に置き換えました。
ステータス 根拠 置き換えの条件
緑(観測で確認) 21÷k 日を採用率で割った期間、0 件が続いた 期限を過ぎて 0 件
青(機序で確認・観測不能) 原因となる呼び出し自体をコードから外した 差分と根拠を 1 行で書けること
黄(観察中) まだ期限内 観察期限の日付を必ず書く
Claude Code への聞き方も変えました。「このバグを修正済みに落としてよいか」ではなく、「観測で確認できるバグか、機序でしか確認できないバグかを、影響ユーザー数から判定して」と投げます。前者はほぼ毎回「実機で十分にテストしてください」という一般論が返ってきますが、後者は k の値を根拠に答えが分かれます。判定の材料を先にこちらが渡しているかどうかの差です。
次に同じ作業をするときに最初にやること
これから別アプリでも同じデバッグループを回すつもりで、最初にやることを並べておきます。
known-bugs-tracker.md を新規作成して、ステータス凡例(未対応 / 対応中 / 対応済み / 対応不可 / 観察中)を最初に書く
「既知パターン早見表」のヘッダだけ用意して、新規バグが出たら 1 行ずつ追記する
1 セッションでは「コード書く」「Crashlytics 確認する」を混ぜず、最低でも別タブで開く
スタックトレースは Claude Code に投げる前に 4 段(環境 / トップ 5 フレーム / メッセージ / 自分の仮説)に整形する
「直さない」と決めたバグも known-bugs-tracker.md に残し、根拠を Claude Code に書いてもらう
修正を緑に塗る前に 21÷影響ユーザー数 を採用率で割って観察期限を出し、tracker の行に日付として書く
Play Vitals しきい値(クラッシュ 1.09% / ANR 0.47%)が見えてきたら、塩漬け予定を撤回するかどうかを優先順位リストで再判定する
Crashlytics は毎朝開くと一日が荒れるツールですが、こうやって地ならししておくと、新規 issue を見ても「これは既知の BW-017 の変種なので v2.1.1 で消える見込み」と即断できて、コーヒーを飲み終わる前に閉じられるようになります。
毎朝の Crashlytics が少しでも静かになる材料になれば、書いた甲斐があります。長い実装ログにお付き合いいただき、ありがとうございました。