Skip to content

libs/filer: tolerate already-vanished directory during recursive delete#5958

Merged
pietern merged 2 commits into
mainfrom
filer-gcs-recursive-delete
Jul 17, 2026
Merged

libs/filer: tolerate already-vanished directory during recursive delete#5958
pietern merged 2 commits into
mainfrom
filer-gcs-recursive-delete

Conversation

@pietern

@pietern pietern commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

On GCS-backed UC Volumes, a directory created implicitly via CreateParentDirectories has no standalone object, so it disappears when its last child file is deleted. recursiveDelete deletes files first and directories after, so on GCS the directory-delete returns 404 and fails the whole operation even though its goal (directory and contents gone) is already met. This surfaced as databricks fs rm -r failing on GCS volumes.

Map that 404 to a not-found error via apierr.IsMissing and skip not-found directories in recursiveDelete. Correct on every backend: on AWS/Azure the directory-delete still returns 204, so the tolerant branch is never taken.

Cross-verified on live test environments: TestFilerReadWrite/files and TestFilerRecursiveDelete/files now pass on GCP (previously failed) and stay green on AWS.

This pull request and its description were written by Isaac.

On GCS-backed UC Volumes (and potentially S3), a directory created implicitly
via CreateParentDirectories is only a key prefix with no standalone object, so
it disappears when its last child file is deleted. recursiveDelete deletes all
files first and then the directory objects, so on GCS the directory-delete
returns HTTP 404 and fails the whole delete even though its goal (directory and
contents gone) is already satisfied.

Map that 404 to a not-found error in deleteDirectory via apierr.IsMissing (the
SDK maps any 404 to apierr.ErrNotFound; a 404 on the directory-delete endpoint
can only mean the directory is already gone) and skip not-found directories in
recursiveDelete's reverse-order loop. The tolerance is correct on every
backend: on AWS/Azure the directory-delete still returns 204, so the tolerant
branch is never taken.

Observed on the cli-gcp env — the directory delete that fails during recursive
delete returns a 404 with a specific reason:

    DELETE /api/2.0/fs/directories/Volumes/main/<schema>/my-volume/dir/subdir2
    < HTTP/2.0 404 Not Found
    < {
    <   "details": [{ "@type": ".../ErrorInfo",
    <                 "domain": "filesystem.databricks.com",
    <                 "reason": "FILES_API_DIRECTORY_IS_NOT_FOUND" }],
    <   "error_code": "NOT_FOUND",
    <   "message": "The directory being accessed is not found."
    < }

A direct probe (write two files into a dir, delete both, then HEAD/DELETE the
dir) isolates the backend difference:

    Step                                   GCP (cli-gcp)   AWS (cli-aws)
    HEAD dir after writing its files        200 EXISTS      200 EXISTS
    HEAD dir after deleting its files       404 NOT_FOUND   200 EXISTS
    DELETE dir                              404 NOT_FOUND   204 Success

On GCS the implicitly-created directory is a key prefix with no standalone
object, so it vanishes once its last child is deleted; on AWS the directory
persists as an independently-deletable object. All file deletes succeed (204)
before the failing directory delete, so data removal is complete — only the
trailing directory-object delete errored.

Cross-verified against live cli-gcp and cli-aws envs: TestFilerReadWrite/files
and TestFilerRecursiveDelete/files now pass on GCP (previously failed) and stay
green on AWS.

Co-authored-by: Isaac
@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 0976ab2

Run: 29585666758

Env 🔄​flaky 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
💚​ aws linux 4 4 227 1121 4:46
💚​ aws windows 4 4 229 1119 9:08
💚​ aws-ucws linux 4 4 316 1037 6:13
🔄​ aws-ucws windows 1 3 4 318 1035 8:09
🔄​ azure linux 2 4 4 225 1120 5:34
💚​ azure windows 4 4 229 1118 6:45
💚​ azure-ucws linux 4 4 318 1034 6:53
🔄​ azure-ucws windows 2 4 4 318 1032 7:51
💚​ gcp linux 4 4 226 1122 4:45
💚​ gcp windows 4 4 228 1120 6:47
12 interesting tests: 5 flaky, 4 SKIP, 3 RECOVERED
Test Name aws linux aws windows aws-ucws linux aws-ucws windows azure linux azure windows azure-ucws linux azure-ucws windows gcp linux gcp windows
💚​ TestAccept 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
🙈​ TestAccept/bundle/invariant/no_drift 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_indexes/recreate/embedding_dimension 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/ssh/connection 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🔄​ TestFilerWorkspaceFilesExtensionsDelete ✅​p ✅​p ✅​p ✅​p 🔄​f ✅​p ✅​p ✅​p ✅​p ✅​p
🔄​ TestFilerWorkspaceFilesExtensionsRead ✅​p ✅​p ✅​p ✅​p 🔄​f ✅​p ✅​p ✅​p ✅​p ✅​p
🔄​ TestFilerWorkspaceNotebook ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p 🔄​f ✅​p ✅​p
🔄​ TestFilerWorkspaceNotebook/sqlNb.sql ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p 🔄​f ✅​p ✅​p
🔄​ TestFetchRepositoryInfoAPI_FromRepo 💚​R 💚​R 💚​R 🔄​f 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
💚​ TestFetchRepositoryInfoAPI_FromRepo/root 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
💚​ TestFetchRepositoryInfoAPI_FromRepo/subdir 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
Top 10 slowest tests (at least 2 minutes):
duration env testname
8:41 aws windows TestAccept
6:22 azure-ucws windows TestAccept
6:21 gcp windows TestAccept
6:18 azure windows TestAccept
6:14 aws-ucws windows TestAccept
3:07 aws linux TestAccept
3:00 azure linux TestAccept
2:58 gcp linux TestAccept
2:53 azure-ucws linux TestAccept
2:53 aws-ucws linux TestAccept

Comment thread .nextchanges/cli/filer-gcs-recursive-delete.md Outdated
Co-authored-by: Jan N Rose <janniklas.rose@gmail.com>
@pietern
pietern enabled auto-merge July 17, 2026 13:52
@pietern
pietern added this pull request to the merge queue Jul 17, 2026
Merged via the queue into main with commit c5d6e21 Jul 17, 2026
24 checks passed
@pietern
pietern deleted the filer-gcs-recursive-delete branch July 17, 2026 14:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants