Skip to content

reset pending keepalive state on listener handoff during reconfiguration#13712

Open
ZECHEESELORD wants to merge 2 commits intoPaperMC:mainfrom
ZECHEESELORD:fix/keepalive-listener-handoff
Open

reset pending keepalive state on listener handoff during reconfiguration#13712
ZECHEESELORD wants to merge 2 commits intoPaperMC:mainfrom
ZECHEESELORD:fix/keepalive-listener-handoff

Conversation

@ZECHEESELORD
Copy link
Copy Markdown

Fixes PaperMC/Velocity#1723. (The backend side)

During mid session reconfiguration behind Velocity, Paper was carrying the same KeepAlive tracker across listener handoff. That allowed a pending PLAY keepalive expectation to survive into the CONFIG listener.

In the failing case, the sequence was:

  1. the PLAY listener issued keepalive A
  2. listener handoff moved the player into CONFIG
  3. the CONFIG listener inherited the pending expectation for A
  4. the CONFIG listener issued keepalive B
  5. the reply for B arrived while the backend still considered A outstanding
  6. Paper rejected B as stale or out-of-order and disconnected the player with disconnect.timeout

The key signal from backend logging was that listener_handoff showed the CONFIG listener inheriting the prior PLAY expectedId, and the next CONFIG keepalive reply was then rejected as stale_or_out_of_order.

So the failure was not that Velocity dropped the CONFIG reply (the backend received it). The problem was that stale pending PLAY keepalive state leaked across the PLAY -> CONFIG handoff.

the fix:

ServerCommonPacketListenerImpl#createCookie(...) now gives the next listener a fresh KeepAlive instance instead of reusing the current listener's pending tracker. This preserves latency/history state, but intentionally resets inflight keepalive challenge state across listener handoff. In other words:

  • preserve ping history
  • reset pending keepalive expectations

That restores the expected protocol boundary between PLAY and CONFIG.

testing:

Tested locally with the Velocity reproduction from PaperMC/Velocity#1723.

Before this fix:

  • repeated config/unconfig cycles would eventually fail
  • failures were much easier to trigger with added latency
  • backend logs showed CONFIG replies being rejected as out-of-order because the old PLAY expectation was still present

After this fix:

  • no disconnects at 0 ms added latency
  • no disconnects at 200 ms added latency
  • no disconnects at 800 ms added latency
  • backend logs show the CONFIG listener no longer inherits the stale PLAY pending keepalive expectation

@ZECHEESELORD ZECHEESELORD marked this pull request as ready for review March 21, 2026 21:11
@Owen1212055 Owen1212055 added the publish-pr Enables a workflow to build Paperclip jars on the pull request. label Apr 5, 2026
@papermc-pr-publishing
Copy link
Copy Markdown

Last updated for: 3343c9798c5f68a5eeff87de35993a87cf095eb7.

Download the Paperclip jar for this pull request: paper-13712.zip

Maven Publication

The artifacts published by this PR:

Repository Declaration

In order to use the artifacts published by the PR, add the following repository to your buildscript:

repositories {
    maven("https://maven-prs.papermc.io/Paper/pr13712") {
        name = "Maven for PR #13712" // https://github.com/PaperMC/Paper/pull/13712
        mavenContent {
            includeModule("io.papermc.paper", "dev-bundle")
            includeModule("io.papermc.paper", "paper-api")
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

publish-pr Enables a workflow to build Paperclip jars on the pull request.

Projects

Status: Awaiting review

Development

Successfully merging this pull request may close these issues.

Velocity does not support re-entering the configuration phase from play.

2 participants