Adding a data point and a fix that worked, in case it helps others still stuck here. I hit this on Tails 7.10.1 (Lenovo Yoga, Windows 11), and I think the root cause is a bad CRC-32 checksum in the GPT header rather than anything wrong with the image or the USB stick.
What I ruled out first: three different USB drives, both Rufus and balenaEtcher (Etcher’s verification pass came back clean), both USB-A and USB-C ports, Secure Boot off, confirmed UEFI boot mode. Every attempt failed identically.
Windows saw the stick as completely healthy. In PowerShell, Get-Partition -DiskNumber 1 | Get-Volume returned FileSystem FAT32, FileSystemLabel TAILS, HealthStatus Healthy, with only ~4 MB free of 1.78 GB — exactly what a correct image write looks like.
But at the grub> prompt, ls -l showed:
Device hd0: No known filesystem detected - Sector size 512B - Total size 60416000KiB
Device hd1: No known filesystem detected - Sector size 512B - Total size 1000204632KiB
Partition hd1,gpt4: No known filesystem detected
Partition hd1,gpt3: No known filesystem detected
Partition hd1,gpt2: No known filesystem detected
Partition hd1,gpt1: Filesystem type fat - Label ‘SYSTEM_DRV’
hd0 is the USB (60416000 KiB = 57.6 GiB, matches Disk Management). GRUB reads its size and sector size correctly but finds zero partitions on it, while parsing all four partitions on the internal drive and reading its FAT32 ESP without trouble. So GRUB’s GPT parser, FAT driver, and block I/O all work — they just reject this particular table. search --no-floppy --label TAILS --set=root returned “error: no such device: TAILS”, and $cmdpath was empty.
The explanation: GPT stores a CRC-32 in the header computed over the partition entry array. The entry bytes on the stick are correct, but the checksum over them is wrong. This is documented as Rufus issue #954 (GUID Partition Table (GPT) header contains invalid CRC-32 checksum of GPT entries array · Issue #954 · pbatard/rufus · GitHub) — the entries match the source image byte for byte, but the CRC stored in the header does not. Windows validates loosely and mounts it anyway; GRUB validates strictly per spec, decides the table is untrustworthy, and discards it entirely. The firmware still loads grubx64.efi because it uses its own file-loading path, which never touches the GPT — which is why you get a working grub> prompt that can’t see the drive it booted from.
The fix (TestDisk, ~1 minute, no second machine or Linux install needed):
- Download TestDisk from cgsecurity.org and run testdisk_win.exe as Administrator
- Skip the log, then select your USB drive — check the size and model carefully, do not pick your system disk
- Partition table type: EFI GPT
- Analyse
- The listing should show one partition: EFI System, start 2048, [EFI System Partition] [TAILS]. Press P to list files — you should see .disk, EFI, LIVE, SYSLINUX, UTILS, which confirms it’s reading the FAT at the right offset. Press q to go back.
- Press Enter, then select Write and confirm with Y
Two things that tripped me up: do NOT run Quick Search. It found duplicate “MS Data” entries at sectors 2054 and 2060 that are scan artifacts, not real partitions. If you do run it, make sure only the 2048 EFI System entry is flagged P and everything else is D before writing. Also, the Write option was below the visible area of my console window and I had to scroll down to reach it.
After writing, quit TestDisk, eject the stick, and shut down rather than restarting — pull the stick while the machine is off. That keeps Windows from remounting it before you boot. Booted straight to the Tails menu on the first try.
This fixed it on the existing stick with no rewrite, which also means the downloaded image was fine the whole time. The heads/cylinder mismatch warnings TestDisk shows are cosmetic — FAT32 records a legacy CHS geometry that nothing modern reads.
One caveat: not everyone hits this, so it likely depends on something specific to the drive or the Windows storage stack. But if your grub> ls shows the USB as a whole disk with no partitions under it while your internal drive parses fine, this is almost certainly what you’re looking at.