FlutterのCrashlytics完全対応:AI時代のクラッシュ分析と優先度の付け方 – YOUTRUST Tech Blog


はじめに

YOUTRUSTでアプリエンジニアをやっているオカ
( YOUTRUST / X )です。前職では長くネイティブアプリの開発を行っていて、Flutter開発に移って気づいたことがあります。Flutterのクラッシュ対応はネイティブアプリとは全然違う部分が多くあります。さらに2023年以降はAIの登場でモバイルアプリのクラッシュ対応方法が大きく変化しました。

この記事では、YOUTRUSTでの実例を交えながら、現実的なクラッシュ対応の方法を紹介します。

第1章:Flutterは「落ちない」?その真相

ネイティブ開発者が最初に困惑すること

ネイティブアプリ開発からFlutterに来ると、こんな体験をします。

class _HomeScreenState extends State {
  void _onButtonPressed() {
    Navigator.push(context, MaterialPageRoute(builder: (_) => DetailScreen()));

    Future.delayed(Duration(milliseconds: 500), () {
      setState(() {
        
      });
    });
  }
}




「エラーが出てるのに落ちないぞ?」って驚きますよね。

なぜ落ちないのか

Flutterは「一部でエラーが起きても、他は動き続けてほしい」という設計です。画像の読み込みに失敗しても、テキストは表示されるべき、みたいな。

でも、これには落とし穴があります。

void main() {
  runApp(MyApp());
}


void main() {
  FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;
  PlatformDispatcher.instance.onError = (error, stack) {
    FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
    return true;
  };
  runApp(MyApp());
}

設定しないと、エラーは発生しているのにCrashlyticsには何も記録されません。開発中のコンソールには出てるのに、本番環境で何が起きてるか分からない、という状況になります。

よくある落とし穴:Hot Reloadの罠

もう一つ、厄介な問題があります。

みんな大好きHot Reloadにも罠があります。

class _ProfileScreenState extends State {
  late User _user; 

  @override
  Widget build(BuildContext context) {
    return Text(_user.name); 
  }
}

開発中はHot Reloadで前の状態が残ってるから問題なく動作します。でも本番では完全に新規起動なのでクラッシュします。

ベテランでも油断するとハマります。「動いてるから大丈夫」って思い込んじゃうんですよね。

⚠️ lateキーワードは特に注意が必要

lateは便利ですが、初期化を忘れるとランタイムエラーになります。可能な限り以下のような安全な方法を使いましょう

class _ProfileScreenState extends State {
  User? _user;

  @override
  Widget build(BuildContext context) {
    return Text(_user?.name ?? '読込中');
  }
}


class _ProfileScreenState extends State {
  User _user = User.empty();

  @override
  Widget build(BuildContext context) {
    return Text(_user.name);
  }
}

ちなみにHot Reloadには簡単な?対策が存在します。

対策

# 定期的にリリースビルドでテスト
flutter run --release

第2章:YOUTRUSTの現状

できてること

基本的なエラーキャッチ

FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;
PlatformDispatcher.instance.onError = (error, stack) { ... };

reasonパラメータで文脈記録

FirebaseCrashlytics.instance.recordError(
  error,
  stack,
  reason: 'API request failed during checkout'
);

クラッシュが発生した場合は、Slackにリアルタイムで通知が飛ぶようになっています。
内容をアプリエンジニアが確認して、問題があればチケット化して優先度を決めて対応する流れになります。

改善できる部分

カスタムキーが未設定

カスタムキーがないと、こんなことになります:

クラッシュ発生
→ スタックトレースを見る
→ なぜ起きたか分からない
→ 再現しようとするが条件不明
→ 数日〜数週間の調査...

でも、カスタムキーがあればこうなります:

{
  'feed_item_type': 'post',
  'has_media': false,
  'scroll_position': 3,
  'is_initial_load': false,
  'cache_available': true,
  'reason': 'Failed to render feed item'
}



AIを使ってクラッシュに対応するためにも、少しでも多くの情報を取得できるような対応が今後必要になります。

第3章:AIが変えたクラッシュ対応

2022年以前のやり方

典型的なクラッシュ対応:

  1. Crashlyticsでスタックトレース確認(10分)
  2. コード読んで原因推測(1-2時間)
  3. 再現条件を探す(2-4時間)
  4. 修正コード書く(30分-1時間)
  5. レビュー・テスト(2時間)

合計:6-9時間

しかも「前にも似たようなの見たな…」って思っても、その知見がなかなか見つからないので多くの場合、属人化するんですよね。

2023年以降:AIの登場

同じクラッシュ対応が…

1. Crashlytics確認(5分)

2. Claudeにスタックトレース貼り付け

    「このエラーの原因と対策を教えて」→ 30秒で回答

3. 修正コード生成依頼

    「修正したコード書いて」→ 5分でコード生成

4. レビュー・テスト(1時間)

合計:1-2時間

約75%の時間削減!(6時間 → 1.5時間の場合)

 実例1:dispose後のエラー(2025年10月)
 - スタックトレース確認(5分)
 - Claudeにエラー内容を貼り付けて原因分析(30秒)
 - 修正コード生成依頼(5分)
 - レビュー・テスト(30分)
 PR作成からマージまで:1時間

AIが出てきて一番変わったのは、不具合の推定が楽になったことです。Flutterでは、実際にクラッシュが起きている箇所と根本原因が異なることが多く、原因特定に時間がかかりがちでした。

AIが効くための前提条件

でも、AIに情報がないと困ります。

❌ 情報不足
「StateErrorが発生しました」
→ AIも汎用的な回答しかできない

✅ 文脈あり
「StateErrorが発生
 - user_tier: premium
 - feature_flag_new_api: true
 - data_source: cache」
→ AIが具体的に分析できる

だからカスタムキーが超重要なんです。

第4章:賢い優先順位の付け方

数字に騙されない

クラッシュフリー率 99% → 94%に急落!
Crashlytics真っ赤!
「Hotfixを!」

でも冷静にクラッシュ情報を確認すると:

  • ユーザーからのクレーム:0件
  • エラー内容:dispose後のsetState
  • 発生箇所:新機能の画面
  • ユーザー体感:なし(画面遷移後)

判断:Hotfix不要。次スプリントで計画的に修正

2週間後にリリースして、クラッシュフリー率99.5%に改善できます。
焦ってHotfix出さなくても問題ありません。

ビジネスインパクト優先

逆に、影響5人でも即対応すべきケース:








→ 即座にHotfix!

判断基準

優先度 = 影響人数 × ビジネスインパクト × ユーザー体感

決済画面:5人 × 最大 × 最悪 = Critical
dispose後:300人 × 低 × なし = Medium

ビジネスインパクトはサービスの存続に関わる場合もあるので、常に気をつけて問題があれば素早く対応する必要があります。

現実的な目標

サービスの実データ

クラッシュフリー率の内訳(仮):
- 99.0%: 本質的なバグ(要修正)
- 0.7%: dispose後のsetState(体感なし)
- 0.2%: 外部要因(ネットワーク、OS不具合)
- 0.1%: 再現不能な一時的エラー

→ 99%を維持しつつ、0.7%を段階的に改善
→ 99.9%を目指すと0.1%のために膨大なコストがかかる

クラッシュフリー率99.9%は目指しません。

理由

  • 99% → 99.9%は指数関数的にコスト増
  • 残り1%は「実害のない」クラッシュも多い
  • dispose後のsetStateのようなケースなど
  • 費用対効果が合わない

第5章:AI時代の未来

2025年の予測

自動修正PRの登場

1. Crashlyticsがクラッシュ検知
2. AIが自動分析
3. 修正コード生成
4. 自動でPR作成
5. 開発者はレビューだけ

技術的には既に可能で、YOUTRUSTでも実装を検討中です。

他にも

リアルタイム予防

PR作成時にAIが警告:
「このコード、画面遷移後にsetStateするとクラッシュしますよ」

今後、こうしたAIツールがさらに進化することでクラッシュ対応が楽になるでしょう。

変わらないもの

でも、最終判断は人間がします:

  • どのクラッシュを優先するか
  • Hotfixか次スプリントか
  • 目標をどう設定するか

AIは強力な助手。でも決断するのは私たち。

まとめ

AI時代のモバイルアプリクラッシュ対応3原則

1. 文脈を記録する

カスタムキーとログで、AIに情報を渡す。

2. 完璧を目指さない

98-99%で十分。残りは費用対効果を考える。

3. 判断は人間が

AIは分析と提案。最終判断は人間が行う。

さいごに

Flutterのクラッシュ対応は、ネイティブアプリとは全く違います。そして、AI時代の今は「AIが活用できる形で情報を記録する」ことが超重要になっています。

完璧なクラッシュフリー率を目指すんじゃなくて、限られたリソースで、最大の効果を引き出す。これが現実的です。

どの開発チームでも、AIを活用すれば効率的に品質を上げられるはずです。

大事なのは完璧じゃなくて、賢く戦うこと。

2025年以降のクラッシュ対応は、Flutterの特性を理解して、AIをフル活用して、賢く優先順位をつける。これがあるべき姿だと思います。


YOUTRUSTではエンジニアを募集しています!

一緒に良いプロダクトを作りませんか?ご応募お待ちしています!
herp.careers


元の記事を確認する

関連記事