Skip to content

IllegalStateException: Dispatching command async on Folia when reward commands fire from region thread events #31

@DimaSergeew

Description

@DimaSergeew

Description

When any earn-exp event triggers a level-up that has reward commands configured, CyberLevels calls Bukkit.dispatchCommand() directly from the event handler. On Folia (and its forks), dispatchCommand requires the global tick thread — calling it from a region thread throws IllegalStateException: Dispatching command async.

The moving event is the most visible trigger because it fires on every player movement, but the same crash will occur with any event (killing, breaking, fishing, etc.) if it causes a level-up while rewards contain commands.

Steps to Reproduce

  1. Run CyberLevels 1.2.5 on a Folia-based server (tested on CanvasMC 26.1.2)
  2. Enable any earn-exp event in earn-exp.yml
  3. Add at least one commands entry to rewards.yml
  4. Have a player trigger the event and reach a reward level

Stack Trace

[Folia Region Scheduler Thread #1/ERROR]: Could not pass event PlayerMoveEvent to CyberLevels v1.2.5
java.lang.IllegalStateException: Dispatching command async
    at io.papermc.paper.threadedregions.RegionizedServer.ensureGlobalTickThread(RegionizedServer.java:149)
    at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:964)
    at org.bukkit.Bukkit.dispatchCommand(Bukkit.java:1132)
    at com.bitaspire.cyberlevels.cache.Rewards$RewardImpl.executeCommands(Rewards.java:117)
    at com.bitaspire.cyberlevels.level.Reward.giveAll(Reward.java:41)
    at com.bitaspire.cyberlevels.BaseSystem$BaseUser.lambda$sendLevelReward$0(BaseSystem.java:479)
    at com.bitaspire.cyberlevels.BaseSystem$BaseUser.sendLevelReward(BaseSystem.java:479)
    at com.bitaspire.cyberlevels.BaseSystem$BaseUser.changeExp(BaseSystem.java:571)
    at com.bitaspire.cyberlevels.BaseSystem$BaseUser.addExp(BaseSystem.java:693)
    at com.bitaspire.cyberlevels.cache.EarnExp.sendPermissionExp(EarnExp.java:494)
    at com.bitaspire.cyberlevels.cache.EarnExp$6.onMovement(EarnExp.java:228)

Environment

  • CyberLevels: 1.2.5
  • Server: CanvasMC 26.1.2-757 (Folia fork)
  • Java: 21

Suggested Fix

In Rewards$RewardImpl.executeCommands, wrap the Bukkit.dispatchCommand() call in a Folia-safe scheduler. For Folia, the command must be dispatched on the global region thread:

// Instead of:
Bukkit.dispatchCommand(sender, command);

// Use:
if (Bukkit.getServer() instanceof io.papermc.paper.threadedregions.RegionizedServer) {
    Bukkit.getGlobalRegionScheduler().run(plugin, task -> Bukkit.dispatchCommand(sender, command));
} else {
    Bukkit.dispatchCommand(sender, command);
}

Metadata

Metadata

Assignees

Labels

bugSomething isn't workinggood first issueGood for newcomers

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions