From b4c46058450525eccaf29f94cc92a4767136c57e Mon Sep 17 00:00:00 2001 From: AndreaBozzo Date: Sat, 17 Jan 2026 14:13:04 +0100 Subject: [PATCH] fix: handle missing indices gracefully in rewrite operation --- rust/lance/src/dataset/transaction.rs | 39 ++++++++++++++++++++------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/rust/lance/src/dataset/transaction.rs b/rust/lance/src/dataset/transaction.rs index 090ef465727..7c2509e51fd 100644 --- a/rust/lance/src/dataset/transaction.rs +++ b/rust/lance/src/dataset/transaction.rs @@ -2523,18 +2523,13 @@ impl Transaction { return Err(Error::invalid_input(format!("An invalid compaction plan must have been generated because multiple tasks modified the same index: {}", rewritten_index.old_id), location!())); } - let index = indices + // Skip indices that no longer exist (may have been removed by concurrent operation) + let Some(index) = indices .iter_mut() .find(|idx| idx.uuid == rewritten_index.old_id) - .ok_or_else(|| { - Error::invalid_input( - format!( - "Invalid compaction plan refers to index {} which does not exist", - rewritten_index.old_id - ), - location!(), - ) - })?; + else { + continue; + }; index.fragment_bitmap = Some(Self::recalculate_fragment_bitmap( index.fragment_bitmap.as_ref().ok_or_else(|| { @@ -4337,4 +4332,28 @@ mod tests { // Verify idx_e removed (bad field) assert!(!indices.iter().any(|idx| idx.name == "idx_e")); } + + #[test] + fn test_handle_rewrite_indices_skips_missing_index() { + use uuid::Uuid; + + // Create an empty indices list + let mut indices = vec![]; + + // Create rewritten_indices referring to a non-existent index + let rewritten_indices = vec![RewrittenIndex { + old_id: Uuid::new_v4(), + new_id: Uuid::new_v4(), + new_index_details: prost_types::Any { + type_url: String::new(), + value: vec![], + }, + new_index_version: 1, + }]; + + // Should succeed (skip missing index) instead of error + let result = Transaction::handle_rewrite_indices(&mut indices, &rewritten_indices, &[]); + assert!(result.is_ok()); + assert!(indices.is_empty()); + } }