PaperMC / PaperMC/Paper

PlayerTeleportEvent called after PlayerQuitEvent when player is inside vehicle.

Open
#13,516 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: needs triage version: 1.21.11
Dominant language
Java
Stars
12.7k
Forks
3.5k
Avg merge
3d 13h
Merged PRs (30d)
11

Description

Expected behavior

PlayerTeleportEvent should not be called after PlayerQuitEvent when a player leaves the server while inside a vehicle (e.g. boat).

This event is called when the Minecraft server teleports a player that is inside a vehicle while leaving the server, after Paper has already called PlayerQuitEvent.

Observed/Actual behavior

As the title says, when a player is inside a vehicle (e.g. a boat) and quits, a dangling PlayerTeleportEvent is called after PlayerQuitEvent has already been called. This might not be a bug/incompatibility, but this also might not be the behavior plugin developers expect.

Stacktrace for the PlayerTeleportEvent called after PlayerQuitEvent below. Note that the IllegalStateException exception is generated internally in the plugin, which only ever occurs if PlayerQuitEvent had been called before PlayerTeleportEvent.

[12:33:18 ERROR]: Could not pass event PlayerTeleportEvent to <plugin> v1.0.0
java.lang.IllegalStateException: <plugin generated message>
        at <plugin>-1.0-SNAPSHOT.jar//<plugin method> ~[?:?]
        at <plugin>-1.0-SNAPSHOT.jar//<plugin class>.onPlayerTeleportEvent(<plugin class>.java:117) ~[?:?]
        at co.aikar.timings.TimedEventExecutor.execute(TimedEventExecutor.java:80) ~[paper-api-1.21.11-R0.1-SNAPSHOT.jar:?]
        at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:71) ~[paper-api-1.21.11-R0.1-SNAPSHOT.jar:?]
        at io.papermc.paper.plugin.manager.PaperEventManager.callEvent(PaperEventManager.java:54) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at io.papermc.paper.plugin.manager.PaperPluginManagerImpl.callEvent(PaperPluginManagerImpl.java:131) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:628) ~[paper-api-1.21.11-R0.1-SNAPSHOT.jar:?]
        at net.minecraft.server.network.ServerGamePacketListenerImpl.teleport(ServerGamePacketListenerImpl.java:1851) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.server.level.ServerPlayer.teleportTo(ServerPlayer.java:2245) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.server.level.ServerPlayer.dismountTo(ServerPlayer.java:2234) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.world.entity.LivingEntity.dismountVehicle(LivingEntity.java:2955) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.world.entity.LivingEntity.stopRiding(LivingEntity.java:3923) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.world.entity.Entity.stopRiding(Entity.java:3328) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.server.players.PlayerList.remove(PlayerList.java:471) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.server.players.PlayerList.remove(PlayerList.java:430) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.server.network.ServerGamePacketListenerImpl.removePlayerFromWorld(ServerGamePacketListenerImpl.java:2259) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.server.network.ServerGamePacketListenerImpl.onDisconnect(ServerGamePacketListenerImpl.java:2237) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.network.Connection.handleDisconnection(Connection.java:820) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.server.network.ServerConnectionListener.tick(ServerConnectionListener.java:244) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.server.MinecraftServer.tickConnection(MinecraftServer.java:1872) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.server.dedicated.DedicatedServer.tickConnection(DedicatedServer.java:549) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.server.MinecraftServer.tickChildren(MinecraftServer.java:1835) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.server.MinecraftServer.tickServer(MinecraftServer.java:1613) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.server.dedicated.DedicatedServer.tickServer(DedicatedServer.java:427) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.server.MinecraftServer.processPacketsAndTick(MinecraftServer.java:1669) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1337) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at net.minecraft.server.MinecraftServer.lambda$spin$2(MinecraftServer.java:388) ~[paper-1.21.11.jar:1.21.11-69-94d0c97]
        at java.base/java.lang.Thread.run(Thread.java:1583) ~[?:?]
Steps/models to reproduce

Inside a Paper plugin, create a Listener that:

  • Contains a Set<Player> seenPlayers;
  • Listens for PlayerJoinEvent and adds the player to the set
  • Listens for PlayerQuitEvent and removes the player from the set
  • Listens for PlayerTeleportEvent and throw if PlayerTeleportEvent#getPlayer is not contained in seenPlayers
  • Join the server, get inside a boat and quit
Plugin and Datapack List

n/a

Paper version
> version
[12:44:32 INFO]: Checking version, please wait...
[12:44:32 INFO]: This server is running Paper version 1.21.11-69-main@94d0c97 (2025-12-30T20:33:30Z) (Implementing API version 1.21.11-R0.1-SNAPSHOT)
You are running the latest version
Previous version: 1.21.10-115-af06383 (MC: 1.21.10)
Other

If I am mistaken and "dangling" player events may be called after PlayerQuitEvent has been called, I think the javadoc should mention this.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the stack-trace entry points in PlayerList.remove, ServerPlayer.dismountTo, and ServerGamePacketListenerImpl.teleport. Reproduce the issue using the described listener, joining a server, entering a boat, and quitting. Done means the event ordering is corrected so no PlayerTeleportEvent follows PlayerQuitEvent, or the relevant javadoc explicitly documents the observed behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.