Sorry for the late reply; I haven’t had time to post recently.
I did get it fixed thanks to @sonofcy! On their suggestion I had a second look through the relevant issues of the ESPUI library. I found a thread that discussed this problem. It was fairly far down on the list, and used some odd terminology in the title, which is why I didn’t pick up on it the first time round.
Half of it was in Russian, but I did manage to figure out what was going on. I turns out that ESPUI uses the me-no-dev ESPAsyncWebServer library, but the Arduino IDE brings in a different one by default (the lacamera fork), which, according to the posters on the issue is a “bad fork”.
I replaced the installed lacamera fork with the me-no-dev version and everything worked first try.
A huge thanks to everybody who helped my with this problem.