STM32 L4 HAL_FLASH Writes in one function but not another
It appears that the actual issue is that the FLASH_PECR_ERASE (or at least that is what is called on the L0) is left set by the typical flash erase routines.  This causes subsequent program attempts to be some odd and perhaps invalid mix of a program and erase operation.  As mentioned deep in comments below I've previously seen this on an STM32L0, and it seems to be an issue with the STM32L4 here as well.
Original and apparently irrelevant ideas follow

Flash is writing fine in main() and wherever else I try, it's just in this USB write function that it fails.
Why can this not be done in an interrupt context? Both functions I've demonstrated are called in a USB interrupt managed by STM's libraries.

Taking at face value the (perhaps incorrect) belief that this is being called from an interrupt context, you most definitely cannot write to flash from an interrupt by ordinary means.  Writing to flash is a very complex process, a real departure from ordinary chip operation that chips are supposed to hardly ever perform, and very time consuming too.
You'll need to cache the intention to perform a write (save the desire and the data), perform it later from the main loop, and then queue a success or failure response to send back through USB (ie, accept the data immediately, but don't reply if the write worked or not until you have completed it).  Remember to make communication between the interrupt and main loop via safely atomic flags, or use an appropriately brief critical section to make a copy of anything non-atomic.  You will probably need to lock out further modification of the data buffer from the interrupt until you have finished the write, if you cannot do that at the level of the USB buffer itself you may need to DMA from a USB buffer elsewhere in RAM and then write from there.
USB Mass Storage examples are very common.  You can probably learn useful things about how to do the needed decoupling from an example backed by SPI flash rather than internal or from one for a different STM32 if the USB functional block has meaningful similarities in it's architecture with regard to buffering, etc.
If STORAGE_Write_FS() is really being called from an interrupt that is an unfortunate piece of example code.  It may be that there are parts of the architecture of the example which are not yet sufficiently understood - if they give any example backed by actual non-volatile storage (vs faking it with a tiny bit of RAM) a detailed examination of that would be key.