症状: Xcode 26 build database locked が出て、Build、Test、Archiveのいずれかが止まる。
最短の対処: 先に共有ディレクトリを使う同時実行を止め、ジョブごとにDerivedDataを分離します。残留したxcodebuildがないことを確認しても失敗する場合だけ、対象ジョブの構築データベースを清掃し、単独Archiveで復旧を確認してください。
この記事は、SSHでリモートMac上のxcodebuildを動かし、切断や再試行の後にロックエラーが出た独立開発者向けです。複数ジョブを同じプロジェクトで並行実行する小規模チームや、Build・Test・Archiveを一台のMacに集約する環境管理者にも適しています。
最初に残すべき失敗の証拠
最後に表示されたbuild database lockedだけを抜き出すと、実際の所有者や発生順序を失います。まず失敗したジョブについて、次の情報を同じログに保存してください。
- 完全な
xcodebuildコマンド - 実行開始時刻と失敗時刻
- 作業ディレクトリ
DerivedData、OBJROOT、SYMROOT、Archiveの実体パス- 最初に出た有効なエラー
- Build、Test、Archiveを起動したプロセス
- Run Scriptや依存プロジェクトから別のビルドが起動していないか
例として、値を伏せたコマンドは次のようになります。
xcodebuild \
-workspace "/WORKSPACE/Redacted.xcworkspace" \
-scheme "RedactedScheme" \
-configuration Release \
-derivedDataPath "/WORKSPACE/DerivedData/JOB_ID" \
-archivePath "/WORKSPACE/Archives/JOB_ID.xcarchive" \
archive
ここでJOB_IDが実際には固定文字列になっていれば、ジョブ名が異なっていても同じ場所へ書き込みます。Xcodeのビルドシステムと設定値の関係は、AppleのBuild System公式資料およびBuild Settings Referenceで確認できます。
ロックの発生源を分ける
Xcode build database lockedは何が原因なのか
このエラーは、単にキャッシュが古いという意味ではありません。同じビルドデータベースへ別のプロセスが書き込んでいる、異常終了した処理が残っている、または親のxcodebuildが子のビルドを同じ出力先で起動している可能性があります。
最初に次のような同時実行を確認します。
- 手動でBuildを押した直後にCIジョブも開始した
- 失敗したジョブの再試行前に、元のジョブをキャンセルしていなかった
- SSH接続は切れたが、Mac上のプロセスは動き続けている
- 異なるユーザーが同じ作業ディレクトリを使用している
- Build、Test、Archiveが同じ
DerivedDataを参照している
SSH切断後の確認では、プロセス名だけでなく親子関係と開始時刻を見ます。
ps -axo pid,ppid,lstart,command | grep -E 'xcodebuild|XCBBuildService|simctl'
残すべきジョブが決まる前に、すべてのXcode関連プロセスを終了させてはいけません。強制終了すると、テスト結果、xcresult、未完成のxcarchive、アップロード処理、診断ログが不完全になる可能性があります。まず正常終了を待ち、再試行ジョブを止め、最後に所有者が明確なプロセスだけを終了します。
SSH切断後の残留プロセスをどう扱うか
SSHのセッションが消えても、シェルから起動したビルドが同時に消えるとは限りません。CIの実行管理画面、プロセスの親PID、ログの最終時刻を突き合わせ、どのジョブが有効かを判定します。
次の順番なら、成果物を失うリスクを抑えられます。
- 実行中のジョブをCI側でキャンセルする
- 新しいBuild、Test、Archiveを開始しない
- 対象プロセスが正常終了するか待つ
- 残ったプロセスのPID、親PID、作業パスを記録する
- 明らかに不要なジョブだけを終了する
- 終了後に同じPIDや子プロセスが再生成されていないか確認する
テスト結果の保存方法は、Appleのテスト実行と結果解釈の資料にも沿って確認してください。
パス分離とCIの構成
2つのxcodebuildは同じDerivedDataを使えるか
独立したジョブが同じDerivedDataへ同時に書き込む構成は避けてください。ワークスペース名やScheme名が違って見えても、最終的に-derivedDataPath、OBJROOT、SYMROOT、Archiveパスが同じなら、実体は共有状態です。
CIでは、ジョブごとに追跡できるパスを割り当てます。
export JOB_ROOT="/WORKSPACE/jobs/${CI_JOB_ID}"
export DERIVED_DATA="${JOB_ROOT}/DerivedData"
export ARCHIVE_PATH="${JOB_ROOT}/Archives/App.xcarchive"
xcodebuild \
-workspace "/WORKSPACE/App.xcworkspace" \
-scheme "App" \
-derivedDataPath "$DERIVED_DATA" \
-archivePath "$ARCHIVE_PATH" \
archive
CI_JOB_IDのような識別子が空の場合の回避策も必要です。空文字のまま連結すると、複数ジョブが同じ親ディレクトリへ戻るためです。ジョブ開始時に、解決後のパスをログへ出し、実際にディレクトリが異なることを確認してください。
分離するものと集中保存するもの
DerivedData、中間オブジェクト、インデックスはジョブ単位で分離します。一方、完成したxcarchive、dSYM、xcresult、署名済み成果物は、ジョブIDやコミットIDを含む保管先へ移す設計にできます。
| 判定対象 | 共有してよいか | 推奨する扱い | 合格条件 |
|---|---|---|---|
| DerivedData | いいえ | ジョブ固有のパス | 並行ジョブが別ディレクトリへ書く |
| OBJROOT / SYMROOT | いいえ | ジョブ固有のパス | 中間生成物が混ざらない |
| xcarchive | 同じファイルは不可 | ジョブID付きで保存 | 各ジョブに独立したArchiveがある |
| xcresult | 同じファイルは不可 | テスト単位で保存 | 失敗・成功の結果を個別に追跡できる |
| dSYM | 同じファイルは不可 | Archiveと対応付けて保管 | UUIDの照合対象が残る |
| 署名資産 | 無秩序な共有は不可 | 権限を管理して参照 | 秘密鍵とプロファイルの所在が明確 |
Archiveと署名の関係を確認するときは、Appleの配布用署名コードに関する公式資料を参照してください。Archiveを別の場所へ移すことと、署名資産を削除することは同じ操作ではありません。
隠れたネストビルド
Run Script、依存ターゲット、Swift Package関連の処理、配布スクリプトが、親のxcodebuild内から別のビルドを呼び出すことがあります。特にスクリプトが固定の作業ディレクトリや固定のDerivedDataを使う場合、見かけ上は単一ジョブでも同じデータベースを親子プロセスが占有します。
まず次を確認してください。
- Run Scriptに
xcodebuildやビルドラッパーの呼び出しがあるか - 依存ターゲットが意図せず同じ成果物を生成していないか
- スクリプトの入力・出力宣言が実ファイルと一致しているか
- Archive後のアップロード処理が、再度Buildを開始していないか
- 親ジョブと子ジョブで
-derivedDataPathが同じになっていないか
Appleのカスタムスクリプト実行に関する資料では、スクリプトの入力と出力をビルドシステムへ伝える考え方が説明されています。原因がネストビルドなら、いきなり並列ビルドを無効化するのではなく、呼び出し境界、出力の所有者、失敗時の戻し方を決めてから変更します。
修正後は、ログ上で子のxcodebuildが何度起動されたかを確認します。親ジョブが必要な処理を一度だけ実行し、成果物の場所も一意なら、この層の切り分けは完了です。
残留状態の清掃と復旧判定
DerivedDataを削除するとArchiveや署名に影響するか
関連するxcodebuild、テスト、インデックス処理がすべて終了した後であれば、対象ジョブのDerivedDataを削除して再生成する判断ができます。ただし、Archiveや署名資産を同じ親ディレクトリへ置いている構成では、パスを誤ると必要な成果物まで消します。
清掃は狭い範囲から始めます。
- 該当ジョブの一時ディレクトリだけを退避または削除する
- プロジェクト専用の
DerivedDataを再生成する - 同じ完全な
xcodebuildコマンドを単独で実行する - 成功後に
xcresult、Archive、dSYMを確認する - それでも失敗する場合だけ、ワークスペース再生成を検討する
ソースコード、証明書、Provisioning Profile、既存のxcarchive、dSYM、診断ログは、清掃対象から外して保管します。全ユーザーのキャッシュを最初に消す方法は、原因の証拠と他ジョブの復旧材料を同時に失うため、推奨できません。
復旧後の受け入れチェック
次のチェックリストを、単なる再ビルド成功ではなく、運用復旧の判定に使います。
- [ ] 完全なコマンド、作業パス、DerivedDataパスをログに残した
- [ ] 共有パスを使っていた同時実行ジョブを停止した
- [ ]
xcodebuildと関連する子プロセスの残留がない - [ ] Buildを単独で完了させた
- [ ] Testを独立した
xcresultへ保存した - [ ] Archiveを独立した
xcarchiveとして作成した - [ ] dSYMとArchiveの対応を確認した
- [ ] SSH切断後にジョブが意図どおり継続または停止した
- [ ] ジョブキャンセル後に古いプロセスが再生成されない
- [ ] Mac再起動後もパスが再作成される
- [ ] 二つのジョブを実行しても、成果物とログが混ざらない
単独Buildの後に並行Testを戻し、最後に実際のArchiveを実行します。Archiveまで再現しないと、単なる中間生成物の成功を復旧と誤認する可能性があります。Schemeと依存関係は、Scheme設定の公式資料と照合してください。
再発頻度が高い場合は、スクリプト修正、同時実行数の制限、専用Runnerへの分離、別の常駐Mac環境への移行を比較します。GitHub ActionsなどのCIでSwift Packageやアプリを構築する場合も、Appleの継続的インテグレーション向け資料にある実行単位と成果物の考え方を、ジョブごとのパス設計へ反映してください。
既存の環境を先に評価するなら、リモートMacの利用シーンで常駐ビルドに必要な運用条件を確認できます。SSH切断、ジョブキャンセル、ホスト再起動の三つを実際に試しても、独立した作業ディレクトリ、完全なプロセス制御、ログ保存を提供できるなら、現行のMacを使い続けても問題ありません。
一方、共有ディレクトリしか使えない、断線後のプロセスを管理できない、再起動でArchiveやログの所在が失われる環境は、長期的なiOS打ち合わせ用の基盤として不安が残ります。自前のWindowsやLinuxから無理に構成する方法では、Mac専用ツールチェーン、常時稼働、署名資産の管理を別々に補う必要があり、トラブル時の切り分けも複雑になります。短期の検証や一時的な打ち合わせであれば、KVMFLUXのMacレンタル料金を確認し、独立した作業領域と常駐運用を前提にした環境へ切り替える方が、再発条件を減らしやすい選択です。
関連記事
- Xcodeのビルド遅延をTiming Summaryとキャッシュ競合から切り分ける
- クラウドMacでXcode CIを構築し、DerivedDataと依存キャッシュを安全に運用する
- Mac上のセルフホストRunnerを常駐化し、再起動復旧とジョブ分離を確認する
ビルドデータベースのロック問題に、専有Mac環境という選択を
KVMFLUXなら、他の利用者と共有しない物理Mac mini M4を専用のビルドノードとして利用できます。 SSHで接続できるため、残留プロセスの確認や対象ジョブだけの清掃をリモートから安全に進められます。 DerivedDataやシミュレーター関連のデータが増えた場合も、追加SSDでビルド環境の保存領域を拡張できます。 日額・週額・月額・四半期から必要な期間を選び、安定したリモートビルド環境を数分で整えられます。