The Raspberry Pi 5 features a single-lane (x1) PCIe 2.0 interface exposed via a flexible flat cable (FFC) connector. While this is a huge step up from previous Pis, it also introduces compatibility challenges that aren't typically seen with USB.
Here are the main reasons for NVMe drive incompatibilities with M.2 HATs the Raspberry Pi 5:
Pickiness of Controllers: The Raspberry Pi's PCIe implementation is more particular about the controller chip on the NVMe SSD compared to full-fledged desktop motherboards. Some NVMe controllers (e.g., certain Phison controllers like the WD Blue SN550/SN580, WD Green SN350, WD Black SN850/SN770, Kingston NV3, Micron 2450) have proven incompatible or temperamental.
PCIe Generation: The Pi 5's PCIe port is officially Gen 2.0 x1. While you can force it to Gen 3.0 via dtparam=pciex1_gen=3 in config.txt, this is not officially certified and can lead to instability, especially with drives that are very sensitive to PCIe signal integrity or have controllers that don't gracefully downgrade from Gen 3.0. Some controllers, like certain MAP1202-based NVMe drives, may not support PCIe Gen 2.0 backward compatibility and must be forced to Gen 3.0 to work, which then introduces potential instability on the Pi.
Bootloader/Firmware Updates: The Raspberry Pi Foundation has continuously updated the bootloader EEPROM firmware to improve NVMe compatibility and stability. Older firmware versions might not recognize certain drives that newer versions do. Keeping your EEPROM updated is critical.
Power Delivery: The PCIe FFC connector on the Pi 5 can supply a limited amount of power (around 5W). Some high-performance NVMe drives, especially those designed for desktops, can draw significantly more power under load (6-8W or more). If the HAT doesn't have an independent power input (or if it's not used when available), this can lead to instability, crashes, or boot failures.
M.2 is a physical form factor, and it supports different types of drives: NVMe (PCIe-based) and SATA (SATA-based). M.2 HATs for the Pi 5 are specifically designed for NVMe SSDs (M-keyed). If you accidentally try to use an M.2 SATA SSD, it simply won't work electrically, regardless of the HAT.
Most incompatibilities are not due to form factor (2230, 2242, 2280) if the HAT physically accommodates them, but rather the underlying controller.
PCIe M.2 HAT vs. USB M.2 Enclosure
The difference boils down to the interface and how your Raspberry Pi communicates with the storage device.
PCIe M.2 HAT (e.g., Raspberry Pi M.2 HAT+)
USB M.2 Enclosure (USB to NVMe adapter)
Why USB is "more plug-and-play"
USB is designed for universal compatibility with peripherals. When you connect a USB M.2 enclosure, the Pi sees it as a standard USB Mass Storage Device. The operating system has well-established drivers for this, and the bootloader also has robust support for booting from USB drives. There's no direct interaction with the lower-level PCIe protocol or specific NVMe controller quirks from the Pi's firmware perspective; the USB bridge chip handles all that translation.
With PCIe, the Raspberry Pi's bootloader and kernel drivers are directly interacting with the NVMe controller on the SSD at a much deeper hardware level. This direct access allows for higher performance but also means that subtle differences in how NVMe controllers implement the PCIe standard, or how they handle power management, can lead to incompatibilities that are harder to debug. The eeprom and config.txt entries are necessary to enable and fine-tune this direct PCIe interaction.