PaperMC / PaperMC/Paper

PlayerTeleportEvent#setCancelled(true) does not cancel when spectating entity

Open
#14,065 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Expected behavior

PlayerTeleportEvent#setCancelled(true) should cancel teleportation at all times

Observed/Actual behavior

Mounted to an entity (spectator target) in spectator gamemode, teleporting using the spectator menu (using mouse wheel or keyboard numbers) does NOT cancel the teleportation event.

Steps/models to reproduce
  1. Write some code to cancel PlayerTeleportEvent. I used this:
public class Main extends JavaPlugin implements Listener {
    @Override
    public void onEnable() {
        getServer().getPluginManager().registerEvents(this, this);
    }

    // i know Entity shouldn't be cached in a field, but this is just for testing
    private final AtomicReference<Entity> target = new AtomicReference<>();

    @EventHandler
    void onEntityTargetEvent(PlayerStartSpectatingEntityEvent event) {
        Entity entity = event.getNewSpectatorTarget();

        getServer().getScheduler().runTaskLater(this, () -> {
            target.set(entity);
            getLogger().warning("[DEBUG]PlayerStartSpectatingEntityEvent: target.set(entity)");
        }, 1);
    }

    @EventHandler
    void onPlayerTeleportEvent(PlayerTeleportEvent event) {
        if (target.get() == null || event.getCause() != PlayerTeleportEvent.TeleportCause.SPECTATE) {
            return;
        }

        event.setCancelled(true);

        // my specific use-case cannot use Player#getSpectatorTarget
        Entity entity = target.getAndSet(null);
        if (entity == null) {
            return;
        }

        getLogger().warning("[DEBUG]PlayerTeleportEvent: setCancelled(true), cause=SPECTATE");
    }
}
  1. Place down an armor stand.
  2. Get into /gamemode spectator.
  3. Hit the armor stand so it becomes your spectating target.
  4. Teleport to another player using the spectator menu (mouse wheel or keyboard numbers).
  5. See yourself getting teleported to the player, while console logged that the event was canceled.
Plugin and Datapack List
> pl
[17:00:53 INFO]: ℹ Server Plugins (1):
[17:00:53 INFO]: Bukkit Plugins:
[17:00:53 INFO]:  - server-testing

'server-testing' only contains code provided at the reproduce steps

Paper version
> ver
[17:02:35 INFO]: Checking version, please wait...
[17:02:35 INFO]: This server is running Paper version 26.1.2-74-ver/26.1.2@e4e17fc (2026-07-06T16:51:09Z) (Implementing API version 26.1.2.build.74-stable)
You are running the latest version
Previous version: 26.2-40-6d23ced (MC: 26.2)
Other

I have used this code for over 6 years without problems until a player recently found out that he was able to teleport using this flaw.

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 by tracing the PlayerTeleportEvent handling for TeleportCause.SPECTATE, especially the transition from an existing spectator target to a new target selected through the spectator menu. Reproduce the case with the provided Java listener, armor stand, and spectator-menu steps. Done means cancelling the event prevents the player from being teleported while spectating another entity.

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
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.