📌 TL;DR
- S3登録→同期→直後削除→同期で再同期しても消えることのないゾンビナレッジ誕生
- セルフマネージド型のナレッジベースでは再現しない
- ゾンビは
DeleteKnowledgeBaseDocumentsAPI で個別に削除すれば完全に消せる
なお、この挙動は2026年7月時点でAWS公式ドキュメントに記載がなくGAから1ヶ月あまりの新機能なので、今後の改善に期待しつつ現時点の実測記録として読んでください。
🧪 検証環境
| 項目 | 値 |
|---|---|
| リージョン | us-east-1 |
| データソース | S3 |
| ナレッジベース | Managed KB(type: MANAGED) |
🔁 再現手順
- ファイルをS3 に置いて同期
- 同期完了後、すぐにファイルをS3 から削除
- もう一度同期
同期完了してからRetrieve を叩くと消したはずのファイルの中身が返ってきました。
aws bedrock-agent-runtime retrieve \
--knowledge-base-id $KB_ID \
--retrieval-query '{"text": "文書に含まれる適当なキーワード"}' \
--region $REGION
🔍 状態を突き合わせる
まず「今どうなっているのか」を3つの視点で確認しました。
S3 は?
aws s3 ls s3://$BUCKET --recursive --region $REGION
# 何も返らない
ナレッジベース側の文書一覧は?
aws bedrock-agent list-knowledge-base-documents \
--knowledge-base-id $KB_ID --data-source-id $DS_ID \
--region $REGION \
--query 'documentDetails[].{status:status,uri:identifier.s3.uri}'
[
{ "status": "INDEXED", "uri": "s3://.../cross-account-investigation-qiita-v2_1.md" }
]
INDEXED のまま。
S3 に実体がないのにインデックスには居る...
再度同期してみたら?
再度同期しても変わらず...通常の同期エラーであれば再実行で消えるはずなのに消えない。
さらに深く追います。
📜 ログ確認(正常時と発生時のログを比較)
通常時
| 時刻(UTC) | 出来事 |
|---|---|
| 05:16:36 | StartIngestionJob 実行 |
| 05:17:25 | Crawling started |
| 05:17:26 | Crawling completed |
| 05:19:16 | ジョブが COMPLETE |
| 05:22:29 | 文書のADDイベントがログに着地。COMPLETEの3分13秒後 |
ゾンビ発生時
| 時刻(UTC) | 出来事 |
|---|---|
| xx:xx:xx | StartIngestionJob 実行 |
| xx:xx:xx | Crawling started |
| xx:xx:xx | Crawling completed |
| xx:xx:xx | ジョブが COMPLETE |
COMPLETE後のADDイベントはログに出力されていなかった。
いや、待て...まず正常時にCOMPLETEの後になんでADDイベントが出てるの?
💭 私の見解
いろいろなパターンを試して出した見解です。
同期処理(ingestion_job)は待機→処理中→処理完了とステータスが遷移します。
ナレッジに登録されるとCOMPLETEとなり、RetrieveのAPIを叩くと応答される状態になります。
〜ここからは想定になります〜
ナレッジベースにはS3とナレッジのファイルの差分を管理するデータベース的なもの(管理台帳と呼ぶことにする)が内部で存在していてCOMPLETEの後(もしくは非同期)に管理台帳を更新して、
そのタイミングでADDイベントのログが出力されると考えます。
※削除タイミングがADDログの表示前後で再現するしないが分かれるため
つまり私の仮説的には同期ジョブのCOMPLETEはナレッジに情報が登録された完了であって、管理台帳の更新はまだ終わってないことになります。この同期台帳に更新が入る前に次の同期で削除が割り込まれると管理台帳に削除で更新されるのではないかと動きから推測しました。
この時、削除後の同期処理でナレッジが削除されるのでは?と思いますが、この時まだ管理台帳に登録されていないため「削除対象が管理台帳に存在しないため削除実施しない」と考えると辻褄が合います
排他制御はある。ただし守る区間が足りない
ちなみに同期の同時実行の排他制御自体は存在します。同期の実行中に次の同期を打つと、こう弾かれます。
An error occurred (ConflictException) when calling the StartIngestionJob operation:
There is an ongoing ingestion job for this data source with ID H65H2B32ZI.
Retry your request after the ingestion job completes.
問題は、この排他が守っている区間が「ジョブがCOMPLETEになるまで」であることです。実際にはCOMPLETEの後にも非同期の台帳反映が続いているのにそこはノーガードで次の同期を受け付けてしまう。
皮肉なことに、エラーメッセージは「the ingestion job completes を待ってリトライせよ」と案内しています。この案内に素直に従って完了直後にリトライすると、ちょうど事象が発生するタイミングになります。
✅ セルフマネージド型では再現しない
同じ実験をセルフマネージド型のナレッジベース(通常のS3データソース)でも行いましたが、こちらでは再現しませんでした。ファイルを全部消してから同期しても、削除はきちんと実行されます。
ログを見ると、同期の動き自体がそもそも別物です。セルフマネージド型で2ファイルを同期したときの同じログを示します。
| 時刻(UTC) | 出来事 |
|---|---|
| 04:07:32.6 | StartIngestionJob 実行 |
| 04:07:32.8 | クロール完了。2文書が SCHEDULED_FOR_INGESTION(開始から0.2秒) |
| 04:07:34〜36 | 文書ごとの EMBEDDING_STARTED/COMPLETED、INDEXING_STARTED/COMPLETED がリアルタイムに出力される |
| 04:07:37.1 | 2文書とも INDEXED(作成チャンク数つき) |
| 04:07:37.3 | ジョブが COMPLETE。これがログの最後の行 |
文書イベントはすべてジョブ実行中に出力され、COMPLETEイベントがログの最後に来ます。文書単位の処理記録が出そろってからCOMPLETEが宣言されるという順序です。少なくともログで観測できる範囲では、こちらのCOMPLETEは処理がすべて終わってからの合図になっています(実際、完了直後に削除と同期を行っても不整合は起きませんでした)。
🧟 ゾンビナレッジの消し方
残留した文書は再同期では消せませんが、文書を個別指定で削除する DeleteKnowledgeBaseDocuments API なら消せました
aws bedrock-agent delete-knowledge-base-documents \
--knowledge-base-id $KB_ID \
--data-source-id $DS_ID \
--region $REGION \
--document-identifiers '[{"dataSourceType":"S3","s3":{"uri":"s3://'"$BUCKET"'/文書のキー"}}]'
🛡️ 対策
1.削除は直接 DeleteKnowledgeBaseDocuments API を使用する
2.同期実行後にListKnowledgeBaseDocuments APIでS3実態と個別マッチング
3.同期を随時ではな定期バッチに切り替える
他に良い案がある方は是非返信で教えていただければ幸いです。
🏁 おわりに
ナレッジ登録して直後に「あ、間違った。削除しよう」というパターンは普通に起こりうるパターンなので怖いですね。今回の事象が仕様なのかバグなのか不明ですがmanagedKBは内部がブラックボックスなだけに検証では色々なバリエーション確認が必要と改めて感じました。
