Skip to content

fix(commit): verify finalized external manifests#7578

Merged
BubbleCal merged 1 commit into
mainfrom
yang/fix-external-manifest-finalized-fallback
Jul 21, 2026
Merged

fix(commit): verify finalized external manifests#7578
BubbleCal merged 1 commit into
mainfrom
yang/fix-external-manifest-finalized-fallback

Conversation

@BubbleCal

Copy link
Copy Markdown
Contributor

Bug Fix

  • What is the bug?
    ExternalManifestCommitHandler trusted finalized .manifest paths returned by the external manifest store without checking that the object existed.

  • What issues or incorrect behavior does the bug cause?
    A stale finalized V2 path could bypass object-store verification and skip the default V2-to-V1 manifest fallback.

  • How does this PR fix the problem?
    Finalized external manifest locations are now HEAD-checked before use. If the finalized path is missing, resolution falls back through the default version resolver, preserving the V2-first then V1 fallback behavior. The same verification path is used for latest and explicit version resolution.

Validation

  • cargo fmt --all
  • git diff --check -- rust/lance-table/src/io/commit/external_manifest.rs rust/lance/src/io/commit/external_manifest.rs
  • PROTOC=/private/tmp/protoc-35.1-osx-aarch_64/bin/protoc PROTOC_INCLUDE=/private/tmp/protoc-35.1-osx-aarch_64/include cargo test -p lance finalized_external_manifest_location --lib
  • PROTOC=/private/tmp/protoc-35.1-osx-aarch_64/bin/protoc PROTOC_INCLUDE=/private/tmp/protoc-35.1-osx-aarch_64/include cargo clippy --all --tests --benches -- -D warnings

@github-actions github-actions Bot added the bug Something isn't working label Jul 2, 2026
@BubbleCal
BubbleCal force-pushed the yang/fix-external-manifest-finalized-fallback branch 2 times, most recently from 9d0fd93 to 6971630 Compare July 2, 2026 13:22
@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.77778% with 13 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
rust/lance/src/io/commit/external_manifest.rs 90.76% 10 Missing and 2 partials ⚠️
...ust/lance-table/src/io/commit/external_manifest.rs 97.91% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@BubbleCal
BubbleCal force-pushed the yang/fix-external-manifest-finalized-fallback branch from 6971630 to 442310c Compare July 21, 2026 04:50
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Finalized manifest verification

Layer / File(s) Summary
Verify finalized manifest locations
rust/lance-table/src/io/commit/external_manifest.rs
Finalized manifest paths are checked against object-store size and e_tag metadata during latest and version-specific resolution, with fallback on missing objects.
Test verification and I/O behavior
rust/lance/src/io/commit/external_manifest.rs, rust/lance/src/io/commit/s3_test.rs
Tests cover matching metadata, V2-to-V1 fallback, corruption mismatches, and the additional HEAD reads during dataset opening and version checkout.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ExternalManifestStore
  participant ExternalManifestCommitHandler
  participant ObjectStore
  ExternalManifestStore->>ExternalManifestCommitHandler: return finalized ManifestLocation
  ExternalManifestCommitHandler->>ObjectStore: head manifest path
  ObjectStore-->>ExternalManifestCommitHandler: return size and e_tag
  ExternalManifestCommitHandler-->>ExternalManifestStore: return verified or fallback location
Loading

Suggested reviewers: jackye1995

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: verifying finalized external manifests before use.
Description check ✅ Passed The description accurately explains the bug, fix, and validation for the external manifest change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch yang/fix-external-manifest-finalized-fallback

Comment @coderabbitai help to get the list of available commands.

@BubbleCal
BubbleCal marked this pull request as ready for review July 21, 2026 12:34

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
rust/lance-table/src/io/commit/external_manifest.rs (2)

404-409: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Log the stale-finalized-path fallback.

The NotFound branch silently falls back to default_resolve_version with no runtime log, even though this indicates the external store's finalized-path record is stale/wrong — an unexpected condition. The rest of this file (e.g. the put_if_exists failure path) already uses warn! for comparable best-effort/unexpected situations, so a similar log here would help operators detect a systemically stale external store instead of it silently degrading every lookup.

As per coding guidelines, "Choose log levels by audience: use debug! for routine/high-frequency operations, info! for infrequent operator-visible state changes, and warn! for unexpected conditions" and "Log warnings for silent no-op skipped operations, but omit warnings before errors because the error message is sufficient."

📝 Suggested log addition
             Err(ObjectStoreError::NotFound { .. }) => {
                 // The external store may hold a stale finalized V2 path while
                 // the object store still has the manifest at the V1 location.
+                warn!(
+                    "finalized manifest path {} for version {} not found in object store; falling back to default resolution",
+                    location.path, location.version
+                );
                 default_resolve_version(base_path, location.version, object_store).await
             }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rust/lance-table/src/io/commit/external_manifest.rs` around lines 404 - 409,
Add a warn!-level log in the NotFound branch before calling
default_resolve_version, indicating that the external store’s finalized path is
stale and the V1/default resolution fallback is being used. Keep the existing
fallback and other error handling unchanged, and include relevant path/version
context in the warning.

Source: Coding guidelines


507-525: 🚀 Performance & Scalability | 🔵 Trivial

Verified finalized-path flow looks correct.

Matches the tested behavior (happy path fills in missing size/e_tag, V1 fallback on NotFound). Note this adds a mandatory HEAD round-trip to every "resolve latest" call that lands on a finalized manifest (confirmed by the s3_test.rs read_iops bump from 1 to 2) — an accepted correctness-over-latency trade-off, but worth keeping in mind for high-frequency open/checkout paths under load.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rust/lance-table/src/io/commit/external_manifest.rs` around lines 507 - 525,
Preserve the finalized-manifest handling in verify_finalized_manifest_location,
including the HEAD-based metadata resolution and V1 NotFound fallback. Do not
remove or bypass this verification when resolving the latest manifest, and
retain the existing behavior that fills missing size and e_tag values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@rust/lance-table/src/io/commit/external_manifest.rs`:
- Around line 404-409: Add a warn!-level log in the NotFound branch before
calling default_resolve_version, indicating that the external store’s finalized
path is stale and the V1/default resolution fallback is being used. Keep the
existing fallback and other error handling unchanged, and include relevant
path/version context in the warning.
- Around line 507-525: Preserve the finalized-manifest handling in
verify_finalized_manifest_location, including the HEAD-based metadata resolution
and V1 NotFound fallback. Do not remove or bypass this verification when
resolving the latest manifest, and retain the existing behavior that fills
missing size and e_tag values.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Pro Plus

Run ID: df7d26c6-c493-40ef-9763-876c00376580

📥 Commits

Reviewing files that changed from the base of the PR and between 4b6a69a and 442310c.

📒 Files selected for processing (3)
  • rust/lance-table/src/io/commit/external_manifest.rs
  • rust/lance/src/io/commit/external_manifest.rs
  • rust/lance/src/io/commit/s3_test.rs

@BubbleCal
BubbleCal merged commit 741548c into main Jul 21, 2026
33 checks passed
@BubbleCal
BubbleCal deleted the yang/fix-external-manifest-finalized-fallback branch July 21, 2026 14:58
wjones127 pushed a commit that referenced this pull request Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants