This bug has been fixed in the latest build of PaperMC 1.21.1

Description

PaperMC has a critical duplication glitch from versions 1.20.6 to 1.21.1 involving book and quills. Whenever a player attempts to sign a book with a name greater than 15 characters, the player gets kicked with the following error code:

io.netty.handler.codec.EncoderException: Failed to encode packet 'clientbound/minecraft:container_set_slot'

This results in the server reverting to the player’s previous save state—this can be used to duplicate items.

Recreation

Since the server reverts to the player’s previous save state, including the player’s saved inventory items, players can use this exploit in order to duplicate items. The player needs to have a book and quill, along with the item(s) they want to duplicate.

  1. The player logs out with items they want to dupe (and the book and quill) in their inventory.
  2. The player signs the book with an illegal name and gets kicked.
  3. Whenever the player logs back in, the items are on the floor and in the player’s inventory.

For convenience, you can write a Fabric mod to automate this process:

for (int i = 9; i < 44; i++) {
  // ignore book & quill
  if (36 + mc.player.getInventory().selectedSlot == i) continue;
  // throw items
  mc.player.networkHandler.sendPacket(new ClickSlotC2SPacket(
    mc.player.currentScreenHandler.syncId,
    mc.player.currentScreenHandler.getRevision(),
    i,
    1,
    SlotActionType.THROW,
    ItemStack.EMPTY,
    Int2ObjectMaps.emptyMap()
  ));
}
 
// send book update packet
mc.player.networkHandler.sendPacket(new BookUpdateC2SPacket(
  mc.player.getInventory().selectedSlot,
  List.of(":3"), 
  // this can be any string greater than 15 characters
  Optional.of("antidisestablishmentarianismantidisestablishmentarianism"),
));

Demonstration

Patch

This exploit has thankfully been patched in the latest version of PaperMC. Alternatively, you can make a PaperMC plugin that cancels PlayerEditBookEvent events if the title length is greater than 15:

@EventHandler
public void playerEditBook(PlayerEditBookEvent event) {
    if (event.getNewBookMeta().getTitle().length() > 15) {
        event.setCancelled(true);
        Bukkit.getLogger().log(Level.WARNING, event.getPlayer().getName());
    }
}

Tip

You can log, or even automatically ban the player in the event when attempting the exploit