The bug
Cleaning leather armor and shulker boxes using a cauldron in Creative behaves like it does in Survival: The water level of the cauldron is lowered and the item is replaced.
Expected behavior
The expected behavior is that it acts like banners: Right clicking a cauldron only gives the player a new cleaned item (see MC-114104), and everything else remains unchanged.
How to reproduce
Change your gamemode to Creative
/gamemode creative
Place a cauldron with water
/setblock ~1 ~ ~ water_cauldron[level=3]
Right click the cauldron with dyed leather armor
/give @p leather_chestplate{display:{color:0}}
→ ❌ The color was removed from the leather armor and the water level of the cauldron was lowered
Linked issues
relates to
Attachments
Comments

Can confirm for MC 1.12.1.

Can confirm in 1.13-pre3.

Can confirm for MC 1.15.1-pre1

Can confirm in 20w48a (1.17 snapshot)
Can confirm in 21w05a. Update the second reproduction step to the following command, as the current one no longer works.
/setblock ~1 ~ ~ water_cauldron[level=3]
Can confirm in 21w06a.
Can confirm in 21w11a.
Can confirm in 21w13a.
Can confirm in 21w17a.
Can confirm in 1.17.
Can confirm in 1.17.1.
Can confirm in 1.18.2.

In 1.19 Pre-1.
Can confirm in 1.19.
Can confirm in 1.19.2.
Here's a code analysis regarding this issue.
Code Analysis:
The following is based on a decompiled version of Minecraft 1.19.2 using Mojang mappings.
net.minecraft.core.cauldron.CauldronInteraction.java
public interface CauldronInteraction {
...
public static final CauldronInteraction SHULKER_BOX = (blockState, level, blockPos, player, interactionHand, itemStack) -> {
Block block = Block.byItem(itemStack.getItem());
if (!(block instanceof ShulkerBoxBlock)) {
return InteractionResult.PASS;
}
if (!level.isClientSide) {
ItemStack itemStack2 = new ItemStack(Blocks.SHULKER_BOX);
if (itemStack.hasTag()) {
itemStack2.setTag(itemStack.getTag().copy());
}
player.setItemInHand(interactionHand, itemStack2);
player.awardStat(Stats.CLEAN_SHULKER_BOX);
LayeredCauldronBlock.lowerFillLevel(blockState, level, blockPos);
}
return InteractionResult.sidedSuccess(level.isClientSide);
};
...
public static final CauldronInteraction DYED_ITEM = (blockState, level, blockPos, player, interactionHand, itemStack) -> {
Item item = itemStack.getItem();
if (!(item instanceof DyeableLeatherItem)) {
return InteractionResult.PASS;
}
DyeableLeatherItem dyeableLeatherItem = (DyeableLeatherItem)((Object)item);
if (!dyeableLeatherItem.hasCustomColor(itemStack)) {
return InteractionResult.PASS;
}
if (!level.isClientSide) {
dyeableLeatherItem.clearColor(itemStack);
player.awardStat(Stats.CLEAN_ARMOR);
LayeredCauldronBlock.lowerFillLevel(blockState, level, blockPos);
}
return InteractionResult.sidedSuccess(level.isClientSide);
};
...
If we look at the above class, we can see that no checks are carried out to see what gamemode the player is in before modifying the water level of the cauldron along with the dyed item/shulker box that the player is holding. Because of this, when players in creative mode clean dyed items (leather armor) and/or shulker boxes, the water level of the cauldron decreases, and the item that they're cleaning is replaced with the cleaned variant. This shouldn't be the case. Instead, the water level of the cauldron should remain unchanged, and the player should be given a new, cleaned piece of leather armor or shulker box.
Potential Fix:
Adding some "if" statements (such as the one provided below) where appropriate within these pieces of code, to check what abilities the player possesses before allowing the cauldron and the player's held item to be modified, should resolve this problem.
if (!player.getAbilities().instabuild)

Still happening in 1.21.4, however while Leather items get replaced by the cleaned version, shulker boxes seem to be giving you the result as an extra item instead of replacing.
Most likely because the way the code works, it gives you a shulker_box item instead of changing the component/nbt, while the leather items only replace the those values on the same item.
Confirmed for 1.12-pre2