So I, of course, solved it a few hours after posting the issue here by just scheduling the command to execute later.
player.getServer().scheduleInTicks(5, () => {
player.runCommand(`execute in minecraft:overworld run item replace block ${copyx} ${copyy} ${copyz} container.0 with ${book.getId()}${book.getNbt()}`);
})
My educated guess on why this is happening:
I assume you can only interact with the world in the tick event, and not in any other event. So, by scheduling it, it gets executed in a later tick event, and thus works.