Computer Troubles #01
My Encrypted APFS SSD Wouldn’t Mount on macOS — How I Recovered 129 GB Without Paid Software
The password was right, but macOS refused to unlock the drive. The real cause was a handful of unreadable blocks on the SSD. This is how I diagnosed it with built-in macOS commands and copied my files off with the open-source libfsapfs library — without writing a single byte to the failing drive. The tool I used is free on GitHub.
The short version
37,166
files recovered
129 GB
of data recovered
7
files that could not be recovered
$0
spent on software or hardware
- The problem was not the password. A few blocks on the SSD had become unreadable, so macOS could no longer reach the encryption key bag and failed before it even checked the password.
- I opened the SSD read-only with libfsapfs, which reads APFS without the macOS file-system driver, unlocked the volume with my password and copied the files to the Mac’s internal disk.
- Every copied file was checked with SHA-256. Not everything came back: 7 files could not be recovered.
- After the recovery I reformatted the SSD and tested it with F3: all of the roughly 2 TB that was written read back with zero data lost (which is not a guarantee it won’t fail later).
- I turned the scripts into a free tool, APFS Rescue for Mac, available on GitHub.
Read this first
Even read-only access can make a failing drive worse. If the data is irreplaceable and you can afford it, talk to a professional data-recovery service before trying anything. Do not run Disk Utility’s First Aid or Erase on the original drive.
Contents
What happened
| Item | Details |
|---|---|
| Mac | MacBook Pro (Apple silicon), macOS 27.0.1 |
| Drive | Crucial X10 Pro 2 TB (external USB SSD) |
| Format | APFS, encrypted from the Finder after data was already on it |
| Space used | About 225 GB (as reported by macOS) |
Earlier that day the drive unlocked normally with its password. After the Mac restarted, the same password no longer worked.
The symptoms
Listing the volume’s crypto users in Terminal failed with this error:
Error getting list of cryptographic users for APFS Volume: Unable to get list of crypto users for this APFS Volume (-69552)
The system log also said “Passphrase incorrect or user does not exist.” At first glance, that looks like a wrong password.
Diagnosing the drive
Open Terminal (Applications > Utilities > Terminal). Every command in this section is built into macOS and read-only — none of them writes to the drive.
How to read the commands
- Read-only checks that never write to a disk
- Install installs software (does not touch the SSD)
- Admin (sudo) needs sudo; the SSD is still opened read-only
- Writes to disk writes to the disk — double-check the target
1. List external disks
Read-only
diskutil list external physical
Find the line that says Apple_APFS and note its IDENTIFIER (for example disk4s2). The numbers change between Macs and between connections.
/dev/disk4 (external, physical):
#: TYPE NAME SIZE IDENTIFIER
0: GUID_partition_scheme *2.0 TB disk4
1: Microsoft Reserved 16.8 MB disk4s1
2: Apple_APFS Container disk5 2.0 TB disk4s2
2. Check the APFS status
Read-only
diskutil apfs list
Note the encrypted volume’s identifier (for example disk5s1) and look for FileVault: Yes (Locked).
+-> Volume disk5s1 XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
Name: X10 Pro (Case-insensitive)
Mount Point: Not Mounted
FileVault: Yes (Locked)
3. List the volume’s crypto users (the -69552 check)
Read-only
Change this: disk5s1 → your volume identifier from step 2
diskutil apfs listUsers disk5s1
On a healthy volume this prints Cryptographic user for disk5s1 (1 found) followed by the user type (for example Disk User). Mine failed with -69552. Error -69552 has more than one possible cause, so read it together with the kernel log below.
4. Read the kernel log
Read-only
log show --last 2h --style compact --predicate 'process == "kernel" AND eventMessage CONTAINS[c] "apfs"'
This shows APFS-related kernel messages from the last two hours (change 2h to 1d for a full day). Look for I/O error, err 5 or failed to find valid checkpoint repeating for the same block number.
5. Count read errors
Read-only
ioreg -r -c IOBlockStorageDriver -w0 -l | grep '"Statistics"'
Check "Errors (Read)" for each disk. Mine reached 266 just from being plugged in. If the number keeps climbing, keep access to the drive to a minimum.
What went wrong — and what I can’t tell
Reading the log in order made the chain of events clear:
- Read errors at one location: right after the restart, the SSD kept returning
I/O error(err 5) for the same block. - Checkpoints could not be verified: APFS tried to validate its latest checkpoint and the read failed. Older checkpoints pointed to blocks that had already been reused.
- The key bag was out of reach: without a valid checkpoint, macOS could not locate the encryption key bag and failed before checking the password (
APFSVolumeListUUIDsOfUnlockRecords err=2in the log).
So “Passphrase incorrect” was a side effect of not finding the key bag; the password itself was fine. A commercial recovery app’s preview could list the files with the same password, which told me the keys and most of the data were still on the drive.
What I don’t know
I could not determine why part of the SSD became unreadable (the SSD itself or the connection). The explanation above combines facts from the logs with some inference.
What not to do first
| Action | Why |
|---|---|
| Disk Utility First Aid or other repair tools | They write to the disk. Rewriting metadata while some blocks are unreadable can destroy what you need for recovery |
| Erase or reformat | Deletes the data |
| Replugging the drive or retrying the password over and over | macOS reads the disk on every connection attempt |
| Saving recovered files to the same drive | Writes to the failing drive |
Recovering with libfsapfs
libfsapfs is an open-source library that parses APFS on its own. Because it does not depend on the checkpoint validation that macOS got stuck on, it may still find the key bag and your files.
Here is how the free options compared. My constraints: never write to the original SSD, buy nothing, and save to the Mac’s internal SSD (about 557 GB free).
| Method | Result |
|---|---|
| Built-in macOS tools (diskutil, etc.) | Failed: unlock records not found. Repair would write to the disk |
| The Sleuth Kit | The release version could not take an encryption password |
| Imaging the whole drive with ddrescue | Needed 2 TB of free space |
| apfs-fuse | Needed a Linux VM or lowered macOS security settings |
| libfsapfs | Works on macOS as-is, no security changes. Chosen |
The rules I followed:
- Open read-only: open the SSD partition with
O_RDONLY; the code has no write path. - No retries: stop after 20 read errors in total or 3 in a row, and never re-read a block that already failed.
- Keep the password out of logs: type it at a hidden prompt; it never appears in commands or logs.
- Verify with SHA-256: compare the hash computed while reading with the hash of the saved file read back.
- Most important folders first: copy folder by folder, and resume where it stopped.
The core is short: hand a read-only disk to libfsapfs and unlock it with the password (simplified excerpt).
fd = os.open("/dev/rdisk4s2", os.O_RDONLY) # read-only: no writes possible
container = pyfsapfs.container()
container.open_file_object(ReadOnlySource(fd)) # a tiny class with read/seek only
volume = container.get_volume(0)
volume.set_password(getpass.getpass()) # password is not echoed
volume.unlock()
The complete source, with error handling, verification, resume and safety checks, is on GitHub.
Why my one-off scripts aren’t published
The scripts I actually ran contained my SSD’s model name, size, unique IDs and folder names as hard-coded safety checks. They would not work elsewhere, and editing them incorrectly could be dangerous. The same safeguard is built into the public tool as --device, which shows the disk details and asks you to type the device name before reading.
Installing the free tool
APFS Rescue for Mac is a cleaned-up, safer version of my recovery scripts (MIT License). It was tested on macOS 27.0.1 on Apple silicon.
1. Get Python 3.10 or newer
The python3 that ships with macOS is version 3.9, which is too old. With Homebrew (the python.org installer should also work but has not been tested):
Install
brew install python@3.12
2. Download and set up the tool
Download apfs-rescue-for-mac-1.0.0.zip from the GitHub release page and double-click it to unzip. If the folder is in Downloads, run:
Install
cd ~/Downloads/apfs-rescue-for-mac
./setup.sh
This creates a private Python environment inside the folder and installs libfsapfs-python from PyPI, checking every download against pinned SHA-256 hashes. No administrator rights are needed.
Using Python: /opt/homebrew/bin/python3.12 (3.12.13 arm64)
Successfully installed libfsapfs-python-20260921
libfsapfs 20260921 OK
Installed. Try: ./apfs-rescue --help
If you see permission denied, run chmod +x setup.sh apfs-rescue and try again.
Recovering your files
This is the workflow for a disk image. Replace ~/Desktop/disk.img with your own image file.
1. Inspect the image (no password needed)
Read-only
Change this: ~/Desktop/disk.img → your image file
./apfs-rescue info ~/Desktop/disk.img
container : offset=20480 size=1073700864 (1.07 GB) GPT partition 1 'disk image'
volumes : 1
[0] name='RescueTestA' encrypted/locked=True
2. List the top-level folders
Read-only
Change this: ~/Desktop/disk.img → your image file
./apfs-rescue list ~/Desktop/disk.img --depth 1
You will be asked for the volume password (it is not shown as you type). Only the folder listing is read, not file contents.
3. Copy the folders you need
Read-only
Change this: ~/Desktop/disk.img and "Documents" → your image file and a folder name from step 2
./apfs-rescue extract ~/Desktop/disk.img --dest ~/Desktop/rescued --path "Documents"
Nothing is written to the source; files are written only to ~/Desktop/rescued. The destination needs the size of the data plus 256 MB free. If the run stops for any reason, run the same command again and it picks up where it left off.
DONE rc=0 saved=8 (6.29 KB) skipped_already_ok=0 not_rescued=0 [io=0 dataless=0 ...]
=== result (all runs into this destination) ===
saved and verified (OK) : 8 files, 6.29 KB
Reading the SSD directly
If you don’t have room for a full disk image (I didn’t), you can read the SSD itself. The tool never picks a disk automatically.
Admin (sudo)
Change this: disk4s2 → the Apple_APFS IDENTIFIER from diskutil list external physical
sudo ./apfs-rescue extract /dev/rdisk4s2 --device --dest ~/Desktop/rescued --path "Documents"
The tool shows the disk details, asks you to type the device name to confirm, then asks for the volume password. It refuses the startup disk, a destination on the same physical disk, and disks with mounted volumes. It stops automatically after 20 read errors in total or 3 in a row.
Verifying the recovered data
Read-only
Change this: ~/Desktop/rescued → the destination from step 3
./apfs-rescue verify --dest ~/Desktop/rescued
This reads every saved file again and checks its size and SHA-256 against the values recorded while reading (it does not touch the SSD). Files that could not be recovered are listed with the reason in _apfs_rescue/not_rescued.tsv.
My results: five runs, most important folders first, all into the same destination. The numbers come from each run’s log.
| Run | Files | Bytes |
|---|---|---|
| 1 | 5,292 | 8,336,917,210 |
| 2 | 955 | 1,201,991,225 |
| 3 | 30,575 | 112,703,498,745 |
| 4 | 321 | 1,293,383,255 |
| 5 | 23 | 5,188,382,618 |
| Total | 37,166 | 128,724,173,053 (about 129 GB) |
- SHA-256: for the 37,143 files from runs 1–4, the hash computed while reading matched the saved file in every case.
- Not recovered: 7 files. One of them was a cloud-only placeholder (a “dataless” file whose contents existed only in cloud storage, not on the SSD).
- Read speed: about 24 MB/s over USB, reading folder by folder.
- Format checks: PDF, JPEG, PNG, Office documents and MP4 files had valid internal structure.
The ~96 GB gap in used space is separate from the 7 files
macOS reported about 224.7 GB in use, while the recovered files total about 128.7 GB — a difference of roughly 96 GB. Much of that difference was large videos I had exported from Final Cut Pro in the past. They were already uploaded to YouTube, so keeping the original exports was not a priority, and when I ran into problems partway through the recovery, I decided not to pursue further recovery or look into the cause.
So the 96 GB is not data confirmed lost for unknown reasons; it is data I chose not to chase. That said, I did not examine the full breakdown of the gap. APFS “used space” can also include things other than file contents, such as file-system metadata, so it is not necessarily the total of recoverable files.
Note that having a video on YouTube does not mean you can get the original high-quality export back. If a video matters to you, keep a backup of the original file somewhere else as well.
What SHA-256 does and doesn’t prove
A match proves that what was read from the SSD is exactly what was saved. APFS has no checksums for file contents, so data that was already corrupt on the SSD cannot be detected this way. I opened my important files to check them.
Testing the SSD after reformatting with F3
After checking the recovered data, I reformatted the SSD and tested whether it could be trusted again. Everything in this section writes to the drive. Never do it before your recovery is finished.
This erases the SSD
Back up the recovered data to a second location before erasing. You can erase in Disk Utility (View > Show All Devices > select the external SSD’s physical device > Erase). Choosing the wrong disk erases a different drive, so double-check the name and capacity. This article intentionally does not show an erase command.
F3 (Fight Flash Fraud) is a free tool that fills a disk’s free space with test data and reads it back to check that nothing was lost or corrupted.
Install
brew install f3
Writes to disk
Change this: /Volumes/X10 Pro → the name of the freshly erased volume (keep the quotes; the name contains a space)
f3write "/Volumes/X10 Pro"
f3read "/Volumes/X10 Pro"
f3write fills all free space with test files (1.h2w and so on) and f3read reads them back and compares. The bigger the drive, the longer it takes. You can delete the test files afterwards.
My result (October 29, 2026)
This is f3read on my Crucial X10 Pro 2 TB after reformatting:
Data OK: 1.82 TB (3904897024 sectors)
Data LOST: 0.00 Bytes (0 sectors)
Corrupted: 0.00 Bytes (0 sectors)
Slightly changed: 0.00 Bytes (0 sectors)
Overwritten: 0.00 Bytes (0 sectors)
Average sequential read speed: 876.13 MB/s
(3904897024 sectors / 36'16")
| Item | Result |
|---|---|
| Read back intact (Data OK) | 1.82 TB (3,904,897,024 sectors = 1,999,307,276,288 bytes) |
| Lost or damaged (Data LOST) | 0 (Corrupted, Slightly changed and Overwritten were all 0 too) |
| Read-back time and speed (f3read) | 36 min 16 s, 876.13 MB/s on average |
| First Aid after reformatting | Completed normally (file system check exit code 0) |
F3 counts in binary units (1 TB = 1024⁴ bytes), which is why a “2 TB” drive shows up as 1.82 TB. I didn’t record how long f3write took or how fast it wrote.
Result: zero data lost. All 3,904,897,024 sectors that were written read back correctly, and First Aid on the reformatted drive completed normally.
What a clean F3 run does and doesn’t tell you
It tells you that, at the time of the test, every area that was written could be read back correctly. It is not a guarantee that the drive won’t fail later. It also doesn’t explain why blocks became unreadable before — the SSD itself, the cable or USB connection, or something else. If you reuse the drive, don’t keep important data only on it; keep a second backup somewhere else.
Troubleshooting
Common messages and what to do (the full list is in docs/troubleshooting.md inside the download):
| Message | Meaning and fix |
|---|---|
could not unlock the volume (wrong password?) | The volume did not unlock. Check the password, including capitalization and keyboard layout |
REFUSED: ... is a disk device | You pointed it at a real disk. If intended, add --device and run with sudo |
REFUSED: confirmation did not match | The typed device name did not match. Type exactly the name shown |
REFUSED: the destination is on the same physical disk | Save to a different disk, such as the Mac’s internal SSD |
REFUSED: a volume on the source disk is mounted | Eject that volume in Disk Utility first |
REFUSED: destination ... is not empty | Choose a new folder; nothing is ever overwritten |
REFUSED: this is a UDIF .dmg image (or similar) | Convert it to a raw image with the command shown, using a new file name |
STOP: I/O error limit reached | Too many read errors. Don’t keep retrying; try other folders or consult a professional |
STOP: destination is almost full | Free up space and run the same command again |
STOP: unexpected error ... unable to open container | The APFS metadata cannot be read; this tool probably cannot recover the volume |
Exit codes: 0 all OK, 1 some files not recovered, 2 refused by a safety check (nothing read or written), 3 stopped (run again to resume), 4 unexpected error, 5 could not unlock, 130 interrupted with Ctrl-C.
What this tool cannot do
- It cannot help if the key bag or the latest file-system metadata itself is unreadable (libfsapfs cannot fall back to older checkpoints).
- Cloud-only files (for example iCloud Drive items set to “Remove Download”) have no data on the disk and cannot be recovered.
- Extended attributes, tags and permissions are not restored (modification times are).
- The public version was tested on artificial disk images. Real bad sectors, real cloud-only files and unlocking with a recovery key were only simulated or not tested.
Lessons learned
- “Wrong password” doesn’t always mean the password is wrong. The kernel log shows which step actually failed.
- Recover first, repair later. First Aid writes to the disk. Don’t write to the original drive until your files are safe and checked.
- Check features in the exact version you’ll use. I planned around a Sleuth Kit feature that existed only in the development branch, not the release.
- Don’t keep data only on an encrypted external drive. Encryption matters, but recovery options are limited when the drive fails. A second backup was the real fix.
FAQ
The password is definitely right, but I get error -69552.
In my case macOS failed to find the key bag before checking the password at all. Check the kernel log for repeated read errors. Keep in mind that -69552 can have other causes too.
Will Disk Utility’s First Aid fix it?
Running a repair while some blocks are unreadable writes to the disk and can destroy information needed for recovery. Recover and check your files first, then decide.
Does it work on Windows or Linux?
This tool is for macOS and was tested only on macOS (Apple silicon). libfsapfs itself also runs on other systems.
What should I do with the SSD afterwards?
Check the recovered files and keep a second backup before erasing or reusing the drive. If F3 reports problems or read errors continue, run the manufacturer’s diagnostic tool or contact them about the warranty.
Download
APFS Rescue for Mac v1.0.0
| File | apfs-rescue-for-mac-1.0.0.zip |
|---|---|
| Where | GitHub release page |
| Source code | GitHub |
| SHA-256 | 2f0788c56a5323a8a38a0762cbff2196238925abde0dd55984ecc5378498994e |
| Tested on | macOS 27.0.1 / Apple silicon / Python 3.12 and 3.14 |
| License | MIT (the libfsapfs-python dependency is LGPL-3.0-or-later; it is not in the ZIP and is downloaded from PyPI during setup) |
To confirm the ZIP has not been tampered with, compare its SHA-256 with the value above:
Read-only
shasum -a 256 ~/Downloads/apfs-rescue-for-mac-1.0.0.zip
References
- libfsapfs (GitHub) — the APFS library (LGPL-3.0-or-later)
- libfsapfs-python (PyPI) — its Python package
- F3 — Fight Flash Fraud (GitHub) — disk read/write verification
- Homebrew — package manager for macOS
This software is provided as is, without warranty. This article is based on a real incident and has been rewritten without personal information. Tool output samples were produced with artificial test data.