Skip to content

Fix dedicated servers crashing on the crafting job toast packet - #220

Open
rubensworks wants to merge 2 commits into
master-1.21-ltsfrom
claude/fix-toast-packet-dedicated-server
Open

Fix dedicated servers crashing on the crafting job toast packet#220
rubensworks wants to merge 2 commits into
master-1.21-ltsfrom
claude/fix-toast-packet-dedicated-server

Conversation

@rubensworks

@rubensworks rubensworks commented Sep 6, 2026

Copy link
Copy Markdown
Member

Problem

All NeoForge server jobs on 26.1.2 and 26.2 fail in CyclopsMC/packtests#72 (failing job):

java.lang.NoClassDefFoundError: net/minecraft/client/gui/components/toasts/Toast
	at integratedterminals/org.cyclops.integratedterminals.proxy.CommonProxy.registerPackets(CommonProxy.java:47)
	at cyclopscore/org.cyclops.cyclopscore.init.ModBaseNeoForge.setup(ModBaseNeoForge.java:260)
Caused by: java.lang.ClassNotFoundException: net.minecraft.client.gui.components.toasts.Toast

CommonProxy.java:47 registers CraftingJobFinishedToastPacket, added in 1.9.0.

CraftingJobFinishedToastPacket.actionClient referred to CraftingJobToast, which implements the client-only Toast. The method was marked @OnlyIn(Dist.CLIENT), but NeoForge stopped stripping @OnlyIn code at runtime in 21.7.3-beta, so the body survives on a dedicated server. Reading the packet's ID/CODEC statics during registration links the class, and the verifier then has to check that CraftingJobToast is assignable to Toast for the toasts.addToast(...) call. That loads Toast, which does not exist on a server.

This is not packtests- or gametest-specific: it breaks every NeoForge dedicated server running IntegratedTerminals 1.9.0 on 26.x. MC 1.21.1 is unaffected at runtime only because NeoForge 21.1 still strips @OnlyIn.

Neighbouring packets such as TerminalStorageIngredientCraftingOptionsPacket are fine despite importing Minecraft: Minecraft.getInstance().execute(...) needs no assignability check against a client type, so the verifier never loads one. That is exactly why this is worth a test rather than a convention.

Change

  • Toast display moves to the client-only CraftingJobToastHelpers. The packet keeps the common work (config check, component lookup, deserialization) and hands the helper typed common values, so the call is an invokestatic with only common parameter types and linking the packet loads nothing client-only. The now-pointless @OnlyIn is dropped.

  • TestPacketsLinkOnDedicatedServer links every class in the packet package through a class loader that hides net.minecraft.client, which is the condition that actually breaks dedicated servers. On the previous code it reproduces the production error exactly:

    Packets failed to link without client classes:
    org.cyclops.integratedterminals.network.packet.CraftingJobFinishedToastPacket: java.lang.NoClassDefFoundError: net/minecraft/client/gui/components/toasts/Toast
    

    It covers all packets rather than just this one, and it does not forbid the safe Minecraft.getInstance() usages that other packets rely on.

Behaviour is unchanged: the same toast, with the same grouping and quantity formatting.

Why a test and not just the fix

A dev run cannot catch this. runGameTestServer runs against the merged client+server jar, so Toast is present and the packet links fine. Only a production dedicated server has the client classes absent, which is why packtests found it and this repo's own CI did not. The test above puts that condition into the normal unit test run.

Validation

./gradlew build and ./gradlew runGameTestServer pass.

Upmerge

This targets master-1.21-lts, where the feature originated, but the actual crash is on master-26-lts and master-26. Those branches use getToastManager(), IngredientComponent.REGISTRY.getValue, and the TagValueInput/TagValueOutput serializer API, so the upmerge needs those adjusted in the new helper.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EBwhTHkNq8t5DCWWg497ye

rubensworks and others added 2 commits September 6, 2026 05:13
CraftingJobFinishedToastPacket referred to CraftingJobToast from its
actionClient method. NeoForge no longer strips @onlyin code at runtime
(removed in 21.7.3-beta), so on a dedicated server the JVM verifier has
to load net.minecraft.client.gui.components.toasts.Toast while linking
the packet class, which fails with a NoClassDefFoundError as soon as the
packet is registered in CommonProxy.

All toast logic now lives in the client-only CraftingJobToastHelpers,
which the packet only calls through an invokestatic with common
parameter types, so nothing client-only is loaded during linking.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EBwhTHkNq8t5DCWWg497ye
The packet now resolves the ingredient component and deserializes the
instance itself, and only hands typed common values to the client-only
helper, instead of passing its raw serialized state along.

Replaces the bytecode scan on this one packet with a test that links
every packet class through a class loader that hides
net.minecraft.client, which is the condition that actually breaks
dedicated servers, and covers all packets rather than just this one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EBwhTHkNq8t5DCWWg497ye
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant