• #Nuxt Content
  • #SQLite
  • #troubleshooting
  • #database
  • #development
未分類

Nuxt Content「database is locked」エラーについて

発生状況

ERROR  [unhandledRejection] database is locked
at StatementWrapper.run (.../db0/dist/connectors/node-sqlite.mjs:44:33)
at deleteDevelopmentCache (.../node_modules/@nuxt/content/dist/module.mjs:375:63)

ファイル名変更やファイル保存時に、@nuxt/contentが開発キャッシュを更新する際に発生する。

原因

Nuxt Contentは開発環境でSQLiteデータベースを使用してコンテンツをインデックス化しています。 ファイル変更を検知した際に、以下の処理がほぼ同時に実行されることがあります:

  1. deleteDevelopmentCache - 古いキャッシュを削除
  2. insertDevelopmentCache - 新しいキャッシュを挿入

SQLiteはデフォルトで1つの書き込み処理のみを許可するため、複数の書き込みが競合するとSQLITE_BUSY (database is locked)エラーが発生します。

特に以下の操作で発生しやすい:

  • ファイル名の変更(aaa.mdnuxt3-drawio-complete-guide.md
  • 複数ファイルの同時保存
  • フロントマターの追加・編集
  • Gitでのファイル切り替え(checkout時など)

対処法

1. 再起動(現状の対処)

# 開発サーバーを再起動
Ctrl+C
pnpm dev

これで問題なく動作する(ユーザー確認済み)

2. SQLiteのタイムアウト設定を調整(根本対策)

nuxt.config.tsに以下を追加:

export default defineNuxtConfig({
  content: {
    database: {
      type: 'sqlite',
      // SQLiteの待機時間を延長(ミリ秒)
      options: {
        busyTimeout: 10000, // 10秒
      }
    }
  }
})

3. ファイル監視の間隔を調整

export default defineNuxtConfig({
  content: {
    watch: {
      enabled: true,
      // 監視のdebounce時間を延長
      debounce: 1000, // 1秒
    }
  }
})

4. Cloudflare D1への切り替え(本番向け)

既にwrangler.tomlでD1設定がある場合、開発環境でも使用可能:

export default defineNuxtConfig({
  content: {
    database: {
      type: 'd1',
      binding: 'DB'
    }
  }
})

なぜ再起動で直るのか

再起動により:

  1. SQLiteデータベースファイル(.nuxt/content-cache.db)のロックが解放される
  2. ファイルシステムウォッチャーがリセットされる
  3. 保留中の書き込みキューがクリアされる

予防策

  1. 大量のファイル操作を避ける:複数ファイルの一括変更はgit操作で行い、開発サーバーを停止してから実行
  2. ファイル保存の間隔を空ける:エディタの自動保存間隔を1秒以上に設定
  3. .nuxtディレクトリを定期的にクリーンrm -rf .nuxtで古いキャッシュを削除

参考情報

結論

現状は再起動で問題なしである。より安定させたい場合はbusyTimeoutの調整を検討すべきである。