RoomとKSPで発生するStorage already registeredエラーの解決方法
このエラーの発生ケースと根本原因
AndroidプロジェクトでRoomデータベースとKSP(Kotlin Symbol Processing)を使用する際、特に新しいType Converterを追加した後に次のエラーが発生します:
log
java.lang.IllegalStateException: Storage for [C:\...\symbolLookups\id-to-file.tab] is already registered
この問題の根本原因は:
- KSPのキャッシュメカニズムが新しいシンボル(例:新規追加したType Converter)を正しく認識しない
- シンボル参照ファイル(
id-to-file.tab
)の更新が競合状態に陥る - プロジェクトの変更内容とKSPキャッシュの同期が失われる
エラーが発生する典型的なシナリオ:
List<String>
などの新たな型に対するType Converterを追加- Roomアノテーションプロセッサが更新内容を検出
- KSPキャッシュと新しいシンボル情報が衝突
即効性のある解決策(一時的回避法)
方法 1:Gradleデーモンの停止
ターミナルで以下を実行:
bash
./gradlew --stop # Gradleデーモンを完全停止
効果:KSPのキャッシュプロセスを強制リセット
方法 2:プロジェクトのクリーン & IDE再起動
- Android Studioで
Build > Clean Project
を実行 File > Invalidate Caches / Restart
を選択- 「Invalidate and Restart」で完全再起動
この方法の限界
一時的に解決しますが、新しいType Converterを追加する度に再発する可能性があります
恒久的な解決策(根本的対策)
KSPの増分処理(Incremental Processing)を無効化する構成が最も効果的:
- プロジェクトルートの
gradle.properties
ファイルを開く - 以下の設定を追加:properties
# KSPの増分処理を無効化 ksp.incremental=false
- ファイルを保存後、プロジェクトを再ビルド
設定の効果:
- KSPがシンボル参照ファイルを再利用しなくなる
- キャッシュ競合の根本原因を解消
- 新規Type Converter追加時の安定性向上
パフォーマンスへの影響
ksp.incremental=false
設定はビルド時間が若干増加する可能性があります。大規模プロジェクトでは影響を計測し、必要に応じて採用を判断してください
予防策とベストプラクティス
- Type Converter管理の統一化:kotlin
@TypeConverters(StringListConverter::class) // 全DAOで共通Converterを使用 abstract class AppDatabase : RoomDatabase()
- KSPバージョンアップ時の注意:
kspVersion
を定期的に更新(例:v1.9.22以降)- 更新履歴で[キャッシュ関連の修正]を確認
- モジュール分割:
- Type Converter専用モジュールを作成
- 変更が頻繁なコンポーネントを分離
推奨ワークフロー
- 新しいType Converter追加時
gradle.properties
にksp.incremental=false
を設定- 変更が安定したら増分処理を再試行(設定削除)
技術的背景と詳細解説
エラーのメカニズム
KSPキャッシュの仕組み
- シンボル参照を
build/generated/ksp
配下に保存 - 変更検知で
id-to-file.tab
を更新 - 問題発生条件:ファイルロック状態での変更試行
RoomとKSPの連携問題
- Roomアノテーション処理がKSPキャッシュと非同期に動作
- 型変換情報の更新がキャッシュ生成プロセスより遅延
- ファイルベースの同期機構が競合を検出し例外発生
ksp.incremental=false
が効果的な理由:
- ビルドごとにキャッシュを完全再生成
- ファイル参照の競合状態を根本的に排除
- プロジェクト構造変更への耐性向上