The bug
A server-side lag spike sometimes occurs when attempting to locate a buried treasure or opening/breaking a chest containing a map. Some players have reported crashes caused by this issue, one of which is attached.
Code analysis
Code analysis by @unknown can be found in this comment.
Linked issues
is duplicated by 10
relates to 1
Attachments
Comments

I have this happen in 22w14a and 15a but it actually crashes my server.
Seed: 1248939201
Coords of close chest that will crash server reliably: /execute in minecraft:overworld run tp @s -170.76 64.00 488.14 -367.35 52.65
I will attach a crash report if this lets me. When I run in normal mode there's only a lag but running as a docker container as server it crashes 100% of the time.
This is my docker-compose config
version: '3'services:
minecraft:
ports:
- "25584:25565"
networks:
- minecraft
volumes:
- "/opt/minecraft_snapshot/data:/data"
environment:
VERSION: "22w15a"
EULA: "TRUE"
TZ: "US/Mountain"
MAX_MEMORY: 16G
MAX_BUILD_HEIGHT: 320
VIEW_DISTANCE: 10
MAX_PLAYERS: 5
CONSOLE: "false"
image: itzg/minecraft-server:java17
restart: always
logging:
driver: loki
options:
loki-url: "http://192.168.1.110:3100/loki/api/v1/push"
exporter:
image: 'nkimball/minecraft_exporter:v6'
environment:
RCON_HOST: minecraft
RCON_PORT: 25585
RCON_PASSWORD: redacted
ports:
- 9784:8000
networks:
- minecraft
volumes:
- /opt/minecraft_snapshot/data/Snapshot:/world:ro
depends_on:
- minecraft
restart: alwaysnetworks:
minecraft:
driver_opts:
com.docker.network.bridge.name: br_snapshot
Also I should note if I play a regular game and open to LAN it doesn't crash, only the server.jar.

This actually seems to also affect other things that are relatively rare, including specific villages (if you search for a snowy village about 4000-5000 blocks away, the lag spike will be very similar). I don't know if it is the same issue.
Edit: it's not the same issue, that is MC-250276.
It's not all boxes with treasure maps either. I teleported around the world seed I posted above and was able to find a shipwreck with a treasure map box that did work @ /execute in minecraft:overworld run tp @s -1402.83 62.00 -970.55 -627.30 31.80
Was also just affected by this.
Disregard. Was a memory issue combined with a slow hard drive.
Ran into this on release version 1.19 ~20 seconds of lag on a single-player world.
On our multiplayer server, it actually times out and crashes due to our watchdog timer. This crash also resulted in duplicated items. We are using Paper, which I understand is not Vanilla, so this part may not be relevant. I do not have a log file (not the server admin), but I can report in our case it hangs without any clear error message until Paper shuts it down.
Seed: -1417780687
Location of Chest: 386, 48, 686 (It has a Buried Treasure map)
EDIT: Not all maps crash/have the same lag spike. My suggestion is it may depend on how far away the X-marks the spot is on the map.
This is affecting me as well with v1.19. I tried it on a server first, which was being killed by Watchdog after a tick exceeded 60 seconds. I moved to single player with the same seed and tried opening the underwater chest, and it did eventually open correctly without crashing, although the entire game stopped processing ticks during that time.
Seed: 1986624035365542
Chest coordinates: -259, 35, -1533
Chest contains a treasure map.
Ran into this on vanilla 1.19.2. Opening the chest caused the integrated server to freeze for over a minute.
Seed: 631889363082005995
Chest coordinates: 10069 52 8909
Same here but really severe using 1.19.2 with paper which isn't vanilla but others are reporting it so I thought I should mention my side. My server crashes every time it tries to open a treasure map chest and if I log out and log back in it makes the treasure map point to no treasure. Also the locate command crashes things as well...

When profiling the server, it seems the issue is when it tries to get the structure position. What seems to be happening is when it tries to sample the heightmap it is taking a very long time, I don't know why.
[media]I have the same issue on my server, this is what I was able to capture.
[16:55:01 ERROR]: Total packets processed on the main thread for all players: 1207
[16:55:01 ERROR]: ------------------------------
[16:55:01 ERROR]: Current Thread: Server thread
[16:55:01 ERROR]: PID: 24 | Suspended: false | Native: false | State: RUNNABLE
[16:55:01 ERROR]: Stack:
[16:55:01 ERROR]: java.base@17.0.2/java.lang.Thread.yield(Native Method)
[16:55:01 ERROR]: net.minecraft.util.thread.BlockableEventLoop.waitForTasks(BlockableEventLoop.java:147)
[16:55:01 ERROR]: net.minecraft.util.thread.BlockableEventLoop.managedBlock(BlockableEventLoop.java:137)
[16:55:01 ERROR]: net.minecraft.server.level.ServerChunkCache.getChunk(ServerChunkCache.java:484)
[16:55:01 ERROR]: net.minecraft.world.level.Level.getChunk(Level.java:503)
[16:55:01 ERROR]: net.minecraft.world.level.LevelReader.getChunk(LevelReader.java:134)
[16:55:01 ERROR]: net.minecraft.world.level.chunk.ChunkGenerator.getStructureGeneratingAt(ChunkGenerator.java:490)
[16:55:01 ERROR]: net.minecraft.world.level.chunk.ChunkGenerator.getNearestGeneratedStructure(ChunkGenerator.java:453)
[16:55:01 ERROR]: net.minecraft.world.level.chunk.ChunkGenerator.findNearestMapStructure(ChunkGenerator.java:382)
[16:55:01 ERROR]: net.minecraft.server.level.ServerLevel.findNearestMapStructure(ServerLevel.java:1904)
[16:55:01 ERROR]: net.minecraft.world.level.storage.loot.functions.ExplorationMapFunction.run(ExplorationMapFunction.java:80)
[16:55:01 ERROR]: net.minecraft.world.level.storage.loot.functions.LootItemConditionalFunction.apply(LootItemConditionalFunction.java:30)
[16:55:01 ERROR]: net.minecraft.world.level.storage.loot.functions.ExplorationMapFunction.apply(ExplorationMapFunction.java:30)
[16:55:01 ERROR]: net.minecraft.world.level.storage.loot.functions.LootItemFunctions.lambda$compose$1(LootItemFunctions.java:58)
[16:55:01 ERROR]: net.minecraft.world.level.storage.loot.functions.LootItemFunctions$$Lambda$4226/0x0000000801491118.apply(Unknown Source)
[16:55:01 ERROR]: net.minecraft.world.level.storage.loot.functions.LootItemFunction.decorate(LootItemFunction.java:13)
[16:55:01 ERROR]: net.minecraft.world.level.storage.loot.functions.LootItemFunction$$Lambda$7344/0x00000008020735a0.accept(Unknown Source)
[16:55:01 ERROR]: net.minecraft.world.level.storage.loot.entries.LootItem.createItemStack(LootItem.java:32)
[16:55:01 ERROR]: net.minecraft.world.level.storage.loot.entries.LootPoolSingletonContainer$1.createItemStack(LootPoolSingletonContainer.java:31)
[16:55:01 ERROR]: net.minecraft.world.level.storage.loot.LootPool.addRandomItem(LootPool.java:71)
[16:55:01 ERROR]: net.minecraft.world.level.storage.loot.LootPool.addRandomItems(LootPool.java:93)
[16:55:01 ERROR]: net.minecraft.world.level.storage.loot.LootTable.getRandomItemsRaw(LootTable.java:95)
[16:55:01 ERROR]: net.minecraft.world.level.storage.loot.LootTable.getRandomItems(LootTable.java:106)
[16:55:01 ERROR]: net.minecraft.world.level.storage.loot.LootTable.getRandomItems(LootTable.java:113)
[16:55:01 ERROR]: net.minecraft.world.level.storage.loot.LootTable.fillInventory(LootTable.java:141)
[16:55:01 ERROR]: net.minecraft.world.level.storage.loot.LootTable.fill(LootTable.java:136)
[16:55:01 ERROR]: net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity.unpackLootTable(RandomizableContainerBlockEntity.java:85)
[16:55:01 ERROR]: net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity.getItem(RandomizableContainerBlockEntity.java:110)
[16:55:01 ERROR]: net.minecraft.world.Containers.dropContents(Containers.java:22)
[16:55:01 ERROR]: net.minecraft.world.Containers.dropContents(Containers.java:13)
[16:55:01 ERROR]: net.minecraft.world.level.block.ChestBlock.onRemove(ChestBlock.java:253)
[16:55:01 ERROR]: net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase.onRemove(BlockBehaviour.java:1009)
[16:55:01 ERROR]: net.minecraft.world.level.chunk.LevelChunk.setBlockState(LevelChunk.java:595)
[16:55:01 ERROR]: net.minecraft.world.level.Level.setBlock(Level.java:552)
[16:55:01 ERROR]: net.minecraft.world.level.Level.setBlock(Level.java:514)
[16:55:01 ERROR]: net.minecraft.world.level.Level.removeBlock(Level.java:678)
[16:55:01 ERROR]: net.minecraft.server.level.ServerPlayerGameMode.destroyBlock(ServerPlayerGameMode.java:414)
[16:55:01 ERROR]: net.minecraft.server.level.ServerPlayerGameMode.destroyAndAck(ServerPlayerGameMode.java:328)
[16:55:01 ERROR]: net.minecraft.server.level.ServerPlayerGameMode.handleBlockBreakAction(ServerPlayerGameMode.java:292)
[16:55:01 ERROR]: net.minecraft.server.network.ServerGamePacketListenerImpl.handlePlayerAction(ServerGamePacketListenerImpl.java:1882)
[16:55:01 ERROR]: net.minecraft.network.protocol.game.ServerboundPlayerActionPacket.handle(ServerboundPlayerActionPacket.java:42)
[16:55:01 ERROR]: net.minecraft.network.protocol.game.ServerboundPlayerActionPacket.a(ServerboundPlayerActionPacket.java:15)
[16:55:01 ERROR]: net.minecraft.network.protocol.PacketUtils.lambda$ensureRunningOnSameThread$1(PacketUtils.java:51)
[16:55:01 ERROR]: net.minecraft.network.protocol.PlayerConnectionUtils$$Lambda$6653/0x0000000801f776f8.run(Unknown Source)
[16:55:01 ERROR]: net.minecraft.server.TickTask.run(TickTask.java:18)
[16:55:01 ERROR]: net.minecraft.util.thread.BlockableEventLoop.doRunTask(BlockableEventLoop.java:153)
[16:55:01 ERROR]: net.minecraft.util.thread.ReentrantBlockableEventLoop.doRunTask(ReentrantBlockableEventLoop.java:24)
[16:55:01 ERROR]: net.minecraft.server.MinecraftServer.doRunTask(MinecraftServer.java:1361)
[16:55:01 ERROR]: net.minecraft.server.MinecraftServer.d(MinecraftServer.java:185)
[16:55:01 ERROR]: net.minecraft.util.thread.BlockableEventLoop.pollTask(BlockableEventLoop.java:126)
[16:55:01 ERROR]: net.minecraft.server.MinecraftServer.pollTaskInternal(MinecraftServer.java:1338)
[16:55:01 ERROR]: net.minecraft.server.MinecraftServer.pollTask(MinecraftServer.java:1331)
[16:55:01 ERROR]: net.minecraft.util.thread.BlockableEventLoop.managedBlock(BlockableEventLoop.java:136)
[16:55:01 ERROR]: net.minecraft.server.MinecraftServer.waitUntilNextTick(MinecraftServer.java:1309)
[16:55:01 ERROR]: net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1197)
[16:55:01 ERROR]: net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:305)
[16:55:01 ERROR]: net.minecraft.server.MinecraftServer$$Lambda$4326/0x00000008014d26e0.run(Unknown Source)
[16:55:01 ERROR]: java.base@17.0.2/java.lang.Thread.run(Thread.java:833)
Hope this gets fixed.
I have found a temporal fix for now
https://github.com/PaperMC/Paper/issues/2312#issuecomment-516988198
Credits for Rvby1

The length of time of the lag spike when getting a treasure map seems to be significantly reduced in 1.19.3 pre-2, but I can't comment for sure whether or not it's been fully fixed.

I can notice improvements, but this is still not fixed in 1.19.3 Pre-release 2.
That moment when even a modern Ryzen 9 CPU is not enough to circumvent this issue completely if the treasure is futher away. Not with PaperMC either. Only pregenning more blocks or disabling works ._.


This is because when generating the loot table, it has to locate a valid buried treasure. This takes time because there are no existing chunks that have a buried treasure strucutre, so it has to generate chunks.
Due to the hidden nature of buried treasure, I think it would be safe to just highly increase the spawn rate of buried treasure, so it is more likely to be closer to treasure maps.

If the issue was that the structure was far away, this issue would have happened in all versions 1.18+ the same way, but the issue just didn't exist in 1.18.x. It's only 1.19.x where the effects are to the point where servers consistently crash with buried treasure not too far away.

The comments here seem like it got a lot worse in some version, so probably the distance of the search is not the only problem. But in case this cannot be fixed in a good way (seems like a computationally hard problem to me), here's an idea for an almost-fix:
While the current set of datapacks would cause such a map to be created, an earlier action (ship or ruin gets generated, villager takes job) could start a new thread that searches for the treasure. The resulting map could be added to a new item tag of the chest or villager that normally does nothing in regular gameplay, but once the chest is opened or the villager is unlocked far enough, the item gets moved into the slot/trade. That way, there's no lag and no timeout.
The problem then still exists if a datapack gets enabled, disabled or reloaded that changes the loot table, but that should almost never happen in regular Survival gameplay, meaning that this issue would affect way less players and way more rarely.
I'm not sure whether removing the treasure chest changes anything about the map (MC-108082 seems to suggest that it doesn't), if that's the case, then that's an edge case that my idea does not cover. Maybe someone else has an idea how to solve that. Maybe a server-wide cache for treasures, similar to portals, regular maps and villager POIs?
The idea works for things that can have NBT, but not for /loot or if a custom datapack adds it to fishing, cat/villager gifts, bartering or advancement rewards. Those would then still be laggy, but I've personally never seen this, except maybe in a loot table randomiser (in which people usually don't even bother with any of these things, because breaking blocks already gives them almost everything).

Still happening in 1.20 and more noticeable especially as the new armour trims are encouraging people to go looking for shipwrecks.

Can someone explain to me why the villagers don't lag when I buy a map that leads to a woodland mansion, which can be thousands of blocks from the village?
But for some reason these ships freeze, it's already unbearable! reproduced in 1.20.1
I don't know if anyone else has this issue, or if this is related (although I'm sure it is) but, because the freeze/lag from opening/breaking a chest with a buried treasure map in it is so bad, the map itself is loaded as an empty map. It still has the title "Buried Treasure Map", but when it's held in the player's hand, it's displayed as an empty, unused map. When right-clicking, it acts like an empty map and shows the area around the player, completely removing the functionality of it being a treasure map.
I've noticed this just now while playing 1.20.1. But I swear that last month, I was playing on a Survival world in the same version (although it was initially created in 1.20) but this was not an issue at all for me then. So I don't know at all what causes the lag or the failure of the map being properly a buried treasure map.
In case it has any impact, I always set my render distance to 16 and my simulation distance to 12. I do play with OptiFine and/or Fabric, but I've tried loading in a completely vanilla client and it all persists regardless.

On multiplayer servers, I have also experienced this freeze when others were exploring shipwrecks. After some attempts over the months, I think I might have a possible solution.
Code Analysis
When using the /locate
command on buried treasure, or when buried treasure maps are generated, eventually the getNearestGeneratedStructure()
method (the random spread one, not the concentric rings one) in net.minecraft.world.level.chunk.ChunkGenerator
is called. This loops over potential structure chunks around the player according to each structure's spread and calls several other methods to determine whether or not the structure can generate there. This includes the findValidGenerationPoint()
method in net.minecraft.world.level.levelgen.structure.Structure
, which is called to return a valid generation point if the generation point is in a valid biome for that structure.
The buried treasure structure has a spread of 1. This means that every single chunk around the player will searched until a buried treasure structure is found. In comparison, other structures usually have much larger spread, meaning only a few specific chunks around the player will be searched. Buried treasure structures are still kept rare despite their small spread using the LEGACY_TYPE_2
frequency reduction method.
While a structure having a spread of 1 alone does not cause a lag spike, its combination with other factors of the buried treasure structure can. The buried treasure structure must calculate the terrain height in order to find its generation point. findGenerationPoint()
calls onTopOfChunkCenter()
in net.minecraft.world.level.levelgen.structure.structures.BuriedTreasureStructure
. And since findGenerationPoint()
is called for every potential structure chunk through findValidGenerationPoint()
, a small spread size of 1 causes the terrain height to be calculated many, many times, creating the observable lag spike.
Code Fix
Similar to normal world generation in the createStructures()
method in net.minecraft.world.level.chunk.ChunkGenerator
, the return value of the method isStructureChunk()
in net.minecraft.world.level.levelgen.structure.placement.StructurePlacement
can be checked before attempting to find a valid generation point in potential structure chunks. This way, potential structure chunks that are not valid structure chunks according to the frequency reduction method are skipped and the terrain height does not have to be calculated many times for buried treasure.
One possible place where this check could be implemented is in the canCreateStructure()
method in net.minecraft.world.level.levelgen.structure.StructureCheck
, which returns whether or not a structure can be generated in a certain chunk.
private boolean canCreateStructure(ChunkPos chunkPos, Structure structure) {
// Get the current structure in a holder.
var structureHolder = this.registryAccess.registryOrThrow(Registries.STRUCTURE).wrapAsHolder(structure);
// Loop through each placement in the structure holder.
for (var placement : this.generatorState.getPlacementsForStructure(structureHolder)) {
// Only if the chunk is a valid structure chunk according to the placement...
if (placement.isStructureChunk(this.generatorState, chunkPos.x, chunkPos.z)) {
// ...continue looking for a valid generation point to determine whether or not a structure will be generated.
return structure.findValidGenerationPoint(new Structure.GenerationContext(this.registryAccess, this.chunkGenerator, this.biomeSource, this.randomState, this.structureTemplateManager, this.seed, chunkPos, this.heightAccessor, structure.biomes()::contains)).isPresent();
}
}
// If all placements were not in structure chunks, return false.
return false;
}
Note that access to the chunk generator state in StructureCheck
is needed in order to call isStructureChunk()
. When constructing net.minecraft.world.level.levelgen.structure.StructureCheck
in net.minecraft.server.level.ServerLevel
, the chunk generator state can passed to StructureCheck
by calling getGeneratorState()
on the field chunkSource
.
Impact
In Minecraft 1.20.4, I measured the time it took to locate a buried treasure structure using the /locate
command after creating a fresh world with seed 6071974100908662531
, both without and with the potential fix.
Structure | Without fix | With fix | Difference |
---|---|---|---|
Buried Treasure | 7329ms | 138ms | -7191ms |
At least for this trial, there was a 5211% increase in speed! To be sure that the fix was not negatively impacting other things, I also measured the time to locate other structures both without and with the potential fix.
Structure | Without fix | With fix | Difference |
---|---|---|---|
Shipwreck | 18ms | 34ms | +16ms |
Mansion | 95ms | 81ms | -14ms |
Pillager Outpost | 110ms | 104ms | -6ms |
Mineshaft | 0ms | 0ms | 0ms |
Igloo | 76ms | 68ms | -8ms |
Swamp Hut | 441ms | 445ms | +4ms |
Buried Treasure (again) | 7399ms | 155ms | -7244ms |
Results indicated that there were no significant changes in the speed of locating other structures without and with the potential fix.
Fix Implementation
I have implemented the fix outlined above in a FabricMC mod for testing purposes, which seems to be successful in resolving the issue. It can be run on both the client and the server. The source code for the mod can be accessed here: https://github.com/bytzo/mc-249136.

I've tested this in three separate world and it seems significantly better on 24w04a. Is anyone still able to reproduce this issue on 24w04a?

This appears to be fixed in Minecraft version 24w04a. I have tested this on the game client and have looked at the code, which both indicate this being fixed.
The method isStructureChunk in StructurePlacement was refactored so that the logic for using a structure's frequency reduction method is in its own method, called applyAdditionalChunkRestrictions. This method is then used before starting to check for a structure in checkStart.
This is a much better solution than the solution I previously wrote since the logic for the frequency reduction method does not require access to a ChunkGeneratorStructureState, so refactoring it out allows for a much cleaner check in StructureCheck. I wrote my solution was in a way so that the game logic would not have to be copied to the mod containing the fix, and I determined that extracting the logic from isStructureChunk would be difficult. So, instead I used the whole method which required a very messy way of accessing a ChunkGeneratorStructureState and structure placement within StructureCheck.
Since this appears to be fixed as of now, I believe this issue can be marked as resolved.

Oops, it looks like this was already marked as resolved while I was checking and writing the below comment. I probably should have refreshed the page before posting, sorry!
playing on version 1.20.4, vanilla server running on Linux, issue is definitely not resolved, found 2 separate shipwreck chests causing the server to crash

1.20.4 is an affected version. This issue was fixed on 24w04a, a 1.20.5 snapshot.
I ran into this issue on a 1.21.1 server. The server lagged and then crashed when opening underwater loot chests with buried treasure maps.
Clones MC-236740, although not nearly as bad.