Skip to content

Don't send keepalive until the client acknowledges FinishedUpdate - #281

Open
KamikotoTkach wants to merge 1 commit into
Elytrium:masterfrom
KamikotoTkach:fix/keepalive-during-config-finish
Open

KamikotoTkach wants to merge 1 commit into
Elytrium:masterfrom
KamikotoTkach:fix/keepalive-during-config-finish

Conversation

@KamikotoTkach

Copy link
Copy Markdown

Problem

Sometimes 26.2 clients get kicked while joining a limbo:

Internal Exception: io.netty.handler.codec.EncoderException: Pipeline has no outbound protocol configured, can't process packet net.minecraft.network.protocol.common.ServerboundKeepAlivePacket

Reconnecting usually works.

Cause

In LimboImpl.spawnPlayerLocal (CONFIG -> PLAY path), LimboAPI writes the config packets that end with FinishedUpdatePacket, switches the encoder to PLAY and calls onConfig. That starts the keepalive task with a 250 ms initial delay.

If the client hasn't acknowledged FinishedUpdate yet (for example, it is still applying the registry sync), the first PLAY keepalive arrives during the client's protocol switch. The client handles it after installing the PLAY inbound protocol and replies right away. If that reply lands between the client sending its FinishConfiguration acknowledgement (a terminal packet, which unconfigures the outbound pipeline) and installing the PLAY outbound protocol, the client throws the exception above and disconnects.

Vanilla servers send nothing between FinishConfiguration and the acknowledgement, so this never happens there.

Fix

Skip keepalive ticks until playTransition completes. It completes in onSpawn(), i.e. once the client has acknowledged the switch, or immediately on the paths that never go through CONFIG (<1.20.2, or PLAY without rejoin). Skipped ticks don't count as missed keepalives, so a slow registry load can't cause a timeout kick from LimboAPI either.

🤖 Generated with Claude Code

The keepalive task starts right after the CONFIG -> PLAY switch packets are
written, with a 250 ms initial delay. If the client is still applying the
registries when it fires, a PLAY keepalive reaches it between sending its
FinishConfiguration acknowledgement and installing the PLAY outbound
protocol; the client answers it immediately and disconnects with
"Pipeline has no outbound protocol configured, can't process packet
ServerboundKeepAlivePacket". Vanilla servers send nothing in this window,
so skip keepalive ticks until the play transition completes.
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