Weather2 Concurrent Packet Fix
A lightweight Mixin patch that fixes a long-standing bug in Weather2, where the game client gets disconnected with the following error:
Failed to encode packet 'clientbound/minecraft:custom_payload'
Caused by: java.lang.RuntimeException: Failed encoding custom payload weather2:nbt_client
Caused by: java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode
at net.minecraft.nbt.CompoundTag.write
This bug has existed for a long time and has not been fixed upstream. This mod serves as a drop-in fix until Weather2 is officially patched.
Root Cause
Weather2 encodes its nbt_client packet from Netty's I/O thread while the game thread simultaneously modifies the same CompoundTag's internal HashMap. Java's HashMap is not thread-safe — concurrent iteration and modification throws ConcurrentModificationException, which Minecraft catches and turns into a client disconnect.
Fix
This mod injects into CompoundTag.write() via Mixin. Before iterating the tag's entries for serialisation, it retries snapshotting the internal map until no concurrent modification occurs:
@Inject(method = "write", at = @At("HEAD"), cancellable = true)
private void safeWrite(DataOutput output, CallbackInfo ci) throws IOException {
// Weather2 modifies tags without any lock, so synchronized(this) is insufficient.
// Retry until a clean snapshot is obtained.
List<Map.Entry<String, Tag>> entries = null;
int attempts = 0;
while (entries == null) {
try {
entries = new ArrayList<>(this.tags.entrySet());
} catch (ConcurrentModificationException e) {
if (++attempts >= MAX_RETRIES) {
// Write empty tag to prevent disconnect as last resort
output.writeByte(0);
ci.cancel();
return;
}
}
}
for (Map.Entry<String, Tag> e : entries) { ... }
ci.cancel();
}
A retry cap of 100 is enforced — if exceeded, an empty tag is written, and a warning is logged to prevent an infinite loop. In practice, the snapshot succeeds within 1–3 attempts.
Compatibility
- Does not modify Weather2 — may works with any version of Weather2
- The patch applies to
net.minecraft.nbt.CompoundTag, a vanilla class — any mod that writes aCompoundTagfrom a non-game thread benefits from this fix - No config required — install and forget
Supported Versions
| File | Loader | Minecraft |
|---|---|---|
weather2patch-x.x.x-neoforge-1.21.jar |
NeoForge | 1.21.1, 1.21 |
weather2patch-x.x.x-neoforge-1.20.1.jar |
NeoForge | 1.20.1 |
weather2patch-x.x.x-forge-1.20.1.jar |
Forge | 1.20.1 |
Requirements
Notes
- This mod patches at the
CompoundTaglevel, not Weather2 specifically. If Weather2 is ever fixed upstream, this mod becomes a no-op (the injection still runs, but the behaviour is identical to vanilla since the fix is purely additive thread-safety). - On first activation, the following message is printed to console:
[weather2patch] CompoundTag thread-safety patch is active. - Tested on NeoForge 21.1.220 + Weather2 2.8.6 + CoroUtil 1.3.8 at accelerated tickrate (1000 ticks/s) for ~20 minutes with zero disconnects.
- I failed to replicate the issue on Forge 47.4.20 - 1.20.1, but I'm going to release a version for it anyway, hope it works 😅 (Updated to the functional version
weather2patch-1.1.2-forge-1.20.1.jar). - Please avoid using the alpha version, as it may not work properly.
- I'm not planning to regularly maintain or add support for other versions of this mod, as it is only a temporary fix for a modpack I am working on. I might change my mind if enough people ask me, though. Also, I'll archive this mod once the Weather2 issue is resolved in the upstream version.

