Skip to content

Mark copied tokens as copies of their copied object#14615

Open
matoro wants to merge 1 commit intomagefree:masterfrom
matoro:undercoveroperative
Open

Mark copied tokens as copies of their copied object#14615
matoro wants to merge 1 commit intomagefree:masterfrom
matoro:undercoveroperative

Conversation

@matoro
Copy link
Copy Markdown
Contributor

@matoro matoro commented Mar 10, 2026

I observed this crash when trying to perform the combo in this test (the real combo casts Astral Dragon first, then Undercover Operative, but reversing them still reproduces the issue and isn't infinite).

Applying this change seems to fix the issue, and makes Undercover Operative behave identically to other clone cards that did not exhibit the issue. The infinite combo still seems to function.

java.lang.ClassCastException: class mage.game.permanent.token.EmptyToken cannot be cast to class mage.game.permanent.Permanent (mage.game.permanent.token.EmptyToken and mage.game.permanent.Permanent are in unnamed module of loader java.net.URLClassLoader @3c98781a)
        at mage.cards.u.UndercoverOperativeApplier.apply(UndercoverOperative.java:59)
        at mage.abilities.effects.common.CreateTokenCopyTargetEffect.apply(CreateTokenCopyTargetEffect.java:218)
        at mage.abilities.AbilityImpl.resolveMode(AbilityImpl.java:232)
        at mage.abilities.AbilityImpl.resolve(AbilityImpl.java:216)
        at mage.abilities.TriggeredAbilityImpl.resolve(TriggeredAbilityImpl.java:279)
        at mage.game.stack.StackAbility.resolve(StackAbility.java:85)
        at mage.game.GameImpl.resolve(GameImpl.java:1842)
        at mage.game.GameImpl.playPriority(GameImpl.java:1763)
        at mage.game.turn.Step.priority(Step.java:73)
        at mage.game.turn.Phase.playStep(Phase.java:205)
        at mage.game.turn.Phase.play(Phase.java:91)
        at mage.game.turn.Turn.play(Turn.java:132)
        at mage.game.GameImpl.playTurn(GameImpl.java:1180)
        at mage.game.GameImpl.play(GameImpl.java:1087)
        at mage.game.GameImpl.start(GameImpl.java:1063)
        at mage.server.game.GameWorker.call(GameWorker.java:35)
        at mage.server.game.GameWorker.call(GameWorker.java:16)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
        at java.base/java.lang.Thread.run(Thread.java:1583)

I observed this crash when trying to perform the combo in this test (the
real combo casts Astral Dragon first, then Undercover Operative, but
reversing them still reproduces the issue and isn't infinite).

Applying this change seems to fix the issue, and makes Undercover
Operative behave identically to other clone cards that did not exhibit
the issue.  The infinite combo still seems to function.

```
java.lang.ClassCastException: class mage.game.permanent.token.EmptyToken cannot be cast to class mage.game.permanent.Permanent (mage.game.permanent.token.EmptyToken and mage.game.permanent.Permanent are in unnamed module of loader java.net.URLClassLoader @3c98781a)
        at mage.cards.u.UndercoverOperativeApplier.apply(UndercoverOperative.java:59)
        at mage.abilities.effects.common.CreateTokenCopyTargetEffect.apply(CreateTokenCopyTargetEffect.java:218)
        at mage.abilities.AbilityImpl.resolveMode(AbilityImpl.java:232)
        at mage.abilities.AbilityImpl.resolve(AbilityImpl.java:216)
        at mage.abilities.TriggeredAbilityImpl.resolve(TriggeredAbilityImpl.java:279)
        at mage.game.stack.StackAbility.resolve(StackAbility.java:85)
        at mage.game.GameImpl.resolve(GameImpl.java:1842)
        at mage.game.GameImpl.playPriority(GameImpl.java:1763)
        at mage.game.turn.Step.priority(Step.java:73)
        at mage.game.turn.Phase.playStep(Phase.java:205)
        at mage.game.turn.Phase.play(Phase.java:91)
        at mage.game.turn.Turn.play(Turn.java:132)
        at mage.game.GameImpl.playTurn(GameImpl.java:1180)
        at mage.game.GameImpl.play(GameImpl.java:1087)
        at mage.game.GameImpl.start(GameImpl.java:1063)
        at mage.server.game.GameWorker.call(GameWorker.java:35)
        at mage.server.game.GameWorker.call(GameWorker.java:16)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
        at java.base/java.lang.Thread.run(Thread.java:1583)
```
@matoro matoro marked this pull request as ready for review March 10, 2026 05:50
@JayDi85 JayDi85 self-assigned this Mar 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants