Skip to content

macOS 26: cleanup fails with "operation not permitted" partway down the filler tree #9

Description

@AndresGonzalez5

What happens

On macOS 26, the post-jailbreak cleanup step can't finish. The jailbreak itself worked fine — this is cleanup-only.

Cleaning 100% |███████████████...███| (5000/5000, 26 it/min)
Cleanup Error: openfdat /Volumes/Kindle/.active_content_sandbox/store/resource/cachedResources/1/2/3/.../3485: operation not permitted

I tried sudo and granting Terminal Full Disk Access; neither made any difference. After the failure the filler tree was still fully intact, a complete 5000 levels deep — nothing had been deleted.

Environment

  • macOS 26.5.2 (build 25F84), Apple M3 Pro (Mac15,6), arm64
  • Kindle 11th Gen (2022) / KT5, firmware 5.19.2.0.1
  • SpringBreak v1.2, springbreak-darwin from the release (universal binary, ran as arm64)
  • Mount: /dev/disk4 on /Volumes/Kindle (msdos, local, nodev, nosuid, noowners, noatime, fskit)

Two things in that mount line seem relevant. fskit means macOS 26 serves FAT/exFAT from a userspace FSKit driver rather than the old kernel extension, so the filesystem behaves differently than on earlier releases. And noowners means every file on the volume is already owned by the invoking user, which would explain why sudo changes nothing.

What I measured

Poking at the volume directly, outside SpringBreak, the failure looks like a path-length limit in the filesystem rather than a permissions problem. Opening directories stops working at exactly 16384 bytes of path:

Depth Path length Result
3484 16383 bytes opens fine
3485 16388 bytes EPERM

Directory 3485 definitely exists — it shows up when you list its parent — it just can't be opened. It's the byte count that matters, not the depth; the cutoff lands exactly where the path crosses 16 KiB. (For contrast, plain absolute-path access on the same volume stops much earlier, at PATH_MAX = 1024 bytes, with a clear ENAMETOOLONG instead of EPERM.)

The odd part is that only opening is affected. Everything else I tried still works past 16 KiB:

Operation Past 16 KiB How I know
creating a directory works the filler step built all 5000 levels on this machine without error
chdir works descending into them works fine
rmdir works rmdir on 3485 from its parent returns a real ENOTEMPTY, not EPERM
rename / move works see below
opening a directory EPERM the failure above

So the bottom ~1500 levels of the tree can't be opened, and since a directory can't be removed until it's empty, they can't be deleted either.

Reproduction

No Kindle needed — any FAT/exFAT volume on macOS 26 should do it:

import os, errno
base = "/Volumes/SOME_FAT_VOLUME/deep"
os.makedirs(base, exist_ok=True)
fd = os.open(base, os.O_RDONLY | os.O_DIRECTORY)
plen = len(base)
for i in range(1, 6000):
    name = str(i)
    os.mkdir(name, dir_fd=fd)              # succeeds past 16 KiB
    try:
        nfd = os.open(name, os.O_RDONLY | os.O_DIRECTORY, dir_fd=fd)
    except OSError as e:
        print(f"blocked at depth {i}, pathlen {plen + 1 + len(name)}: "
              f"{errno.errorcode.get(e.errno)} {e.strerror}")
        break
    os.close(fd); fd = nfd; plen += 1 + len(name)

Expect EPERM on the first directory whose path crosses 16384 bytes.

How I got my own device cleaned up

Since renaming still works past the limit, I moved the unreachable part of the tree somewhere shallow instead of trying to delete it in place. I renamed the blocked directory (3485, at 16388 bytes deep) to sit directly under cachedResources, which dropped its path to about 72 bytes and made the remaining ~1500 levels reachable again. For a 5000-level tree that took exactly one rename. After that, a plain rm -rf .active_content_sandbox finished in 56 seconds and the volume checked out fine.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions