Skip to content

Core: Disallow adding and removing the same file in a rewrite files commit - #17359

Closed
amogh-jahagirdar wants to merge 3 commits into
apache:mainfrom
amogh-jahagirdar:prevent-rewrite-files-add-remove-same-file
Closed

Core: Disallow adding and removing the same file in a rewrite files commit#17359
amogh-jahagirdar wants to merge 3 commits into
apache:mainfrom
amogh-jahagirdar:prevent-rewrite-files-add-remove-same-file

Conversation

@amogh-jahagirdar

@amogh-jahagirdaramogh-jahagirdar commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Relates to #17198

Currently rewrite files allows us to add and remove the same file in a commit. Arguably this is incorrect, as it's an issue with change detection (whether the file was truly added or removed in that commit is ambiguous). It also can lead to ambiguity in file cleanup (though not in the reference implementation's file cleanup since it does a full a reachability analysis).

Comment threadcore/src/main/java/org/apache/iceberg/BaseRewriteFiles.java
private static final RateLimiterStrategy LOW_RATE = RateLimiterStrategy.perSecond(1.0 / 10000.0);

@TempDir private File checkpointDir;
@TempDir private java.nio.file.Path dataDir;

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

not needed, use table.locationProvider().newDataLocation..

Comment on lines +156 to +161
for (DataFile added : addedDataFiles()) {
Preconditions.checkArgument(
!replacedDataFiles.contains(added),
"Cannot add and delete the same file in the same rewrite: %s",
added.location());
}

@dramaticllydramaticllyJul 27, 2026

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.

I am wondering if this is the right place to place the guard, if the goal is to prevent the same file being added and removed in the same snapshot? I think both overwrite-files and row-delta can be abused in a way to achieve the same goal.

On a separate note, knowing this produce incorrect result for the change tracking detection, sometimes such surgical operation can be helpful for stats backfill as to rectify a previously written file with incorrect column level stats, want to see if we shall encourage to use dedicated repair actions such as proposed in #10784

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah I was looking at this in the interim, I think you're right that Overwrite and Row Delta technically allow this and we should block them too.

On a separate note, knowing this produce incorrect result for the change tracking detection, sometimes such surgical operation can be helpful for stats backfill as to rectify a previously written file with incorrect column level stats, want to see if we shall encourage to use dedicated repair actions such as proposed in #10784

Yup! I think rewriting manifests (just like Repair would do) is the right way. After some thought, I don't think updating these operations to infer that add + remove = existing is the right thing to do because I think these APIs have largely been designed around the fact that added = "something new", and removed = "something that existed and we need to remove".

}

@TestTemplate
public void addingAndDeletingSameFileDisallowed() {

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.

I think we might also need to fix a few other tests, namely testReadStreamWithSnapshotTypeRewriteDataFilesIgnoresReplaceMaxFilesAndRows because of

for (Snapshotsnapshot : it) {
if (snapshot.operation().equals(DataOperations.APPEND)) {
Iterable<DataFile> datafiles =
SnapshotChanges.builderFor(table).snapshot(snapshot).build().addedDataFiles();
for (DataFiledatafile : datafiles) {
rewrite.addFile(datafile);
rewrite.deleteFile(datafile);
}
}
}
rewrite.commit();

@github-actions

Copy link
Copy Markdown

This pull request has been marked as stale due to 30 days of inactivity. It will be closed in 1 week if no further activity occurs. If you think that’s incorrect or this pull request requires a review, please simply write any comment. If closed, you can revive the PR at any time and @mention a reviewer or discuss it on the dev@iceberg.apache.org list. Thank you for your contributions.

@github-actions

Copy link
Copy Markdown

This pull request has been closed due to lack of activity. This is not a judgement on the merit of the PR in any way. It is just a way of keeping the PR queue manageable. If you think that is incorrect, or the pull request requires review, you can revive the PR at any time.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@amogh-jahagirdar@dramaticlly@uros-b@anuragmantri