6 min

Gotchas & Troubleshooting

Common mistakes, their symptoms, and how to fix them. Read this before asking for help.

read first
Most issues come from threading violations or incorrect manifest configuration. Check these first before diving deeper.

Threading Violations

symptomcausefix
IllegalStateException: Not on world threadEntity modification outside world.execute()Wrap in player.getWorld().execute(() -> {...})
ConcurrentModificationExceptionModifying collections during iterationCopy collection before modifying or use execute()
Silent failure (code runs but nothing happens)Thread-unsafe component accessAlways use world.execute() for component changes
Random NullPointerExceptionEntity reference became invalidGet fresh references inside execute()
1// WRONG - Will crash or fail silently
2getEventRegistry().register(PlayerConnectEvent.class, event -> {
3 Player player = event.getPlayer();
4 player.setModel("Mouse"); // CRASH!
5});
6
7// CORRECT - Safe execution
8getEventRegistry().register(PlayerConnectEvent.class, event -> {
9 Player player = event.getPlayer();
10 player.getWorld().execute(() -> {
11 player.setModel("Mouse"); // Safe!
12 });
13});

Manifest Issues

symptomcausefix
Plugin not loading at allWrong filenameUse manifest.json, NOT plugin.json
ClassNotFoundExceptionWrong Main class pathCheck Main matches full package path
Plugin loads but start() not calledConstructor doesn't call super()Add super(init) to constructor
NoSuchMethodExceptionWrong constructor signatureMust be public MyPlugin(JavaPluginInit init)
manifest.jsonjson
1{
2 "Group": "com.example",
3 "Name": "my-plugin",
4 "Version": "1.0.0",
5 "Main": "com.example.MyPlugin"
6}
common mistake
The file MUST be named manifest.json. Using plugin.jsonwill cause the plugin to silently fail to load.

MaybeBool Enum

Uses PascalCase, not SCREAMING_CASE:

1// CORRECT
2MaybeBool.True
3MaybeBool.False
4
5// WRONG - Will not compile
6MaybeBool.TRUE // Error!
7MaybeBool.FALSE // Error!

Deprecated Methods

Many methods show deprecation warnings but still work. Use them until replacements are documented:

methodstatusnotes
player.getUuid()Deprecated but worksSafe to use
player.getPlayerConnection()Deprecated but worksRequired for packets
player.getTransformComponent()Deprecated but worksUse for position
world.getPlayers()Deprecated but worksReturns all players
1// These warnings are safe to ignore for now
2@SuppressWarnings("deprecation")
3public void myMethod(Player player) {
4 UUID uuid = player.getUuid(); // Works fine
5 PlayerConnection conn = player.getPlayerConnection(); // Works fine
6}

Compilation Errors

errorcausefix
cannot find symbol: class PlayerMissing importimport com.hypixel.hytale.server.core.entity.entities.Player
incompatible types: double cannot be converted to floatWrong number typeAdd f suffix: 1.0f instead of 1.0
method does not override or implementWrong method signatureCheck exact parameter types
1# Compilation command
2javac --release 21 \
3 -cp "/path/to/HytaleServer.jar" \
4 -d build/classes \
5 src/com/example/*.java

Event Issues

symptomcausefix
Event handler never calledRegistered in setup() instead of start()Move registration to start()
Event called multiple timesRegistered multiple timesOnly register once in start()
event.setCancelled() not workingWrong event priorityUse higher priority or check isCancelled()
Compilation error: wrong register() signatureUsing wrong registration methodSee keyed vs non-keyed events below
1// WRONG - setup() is too early
2@Override
3protected void setup() {
4 getEventRegistry().register(...); // May not work!
5}
6
7// CORRECT - start() is the right place
8@Override
9protected void start() {
10 getEventRegistry().register(...); // Works!
11}

Keyed vs Non-Keyed Events

critical gotcha
Events in Hytale use different registration signatures depending on whether they have a "key" type. Using the wrong one causes compilation errors.

Check if the event extends IBaseEvent<Void> (non-keyed) orIBaseEvent<SomeType> (keyed):

event typekey typeregistration
PlayerConnectEventVoid (non-keyed)register(Class, Consumer)
PlayerReadyEventObject (keyed)register(Class, Object, Consumer)
PlayerChatEventkeyedregister(Class, key, Consumer)
PlayerInteractEventkeyedregister(Class, key, Consumer)
1// NON-KEYED EVENT (like PlayerConnectEvent)
2// Simple registration - just class and handler
3getEventRegistry().register(PlayerConnectEvent.class, event -> {
4 Player player = event.getPlayer();
5 // handle connect
6});
7
8// KEYED EVENT (like PlayerReadyEvent)
9// Requires a key parameter in the middle!
10getEventRegistry().register(PlayerReadyEvent.class, new Object(), event -> {
11 Player player = event.getPlayer();
12 // handle ready
13});
14
15// WRONG - This will NOT compile for keyed events:
16getEventRegistry().register(PlayerReadyEvent.class, event -> {
17 // ERROR: wrong method signature!
18});
If you get a compilation error about register() not accepting your lambda, the event is probably keyed. Check the API docs for the event's key type.

Packet Issues

symptomcausefix
Title not showingWrong packet parametersCheck fadeIn, fadeOut, duration > 0
Particles not visibleWrong position or scaleCheck spawn position is near player
Speed change not applyingMissing fieldsSet ALL speed multiplier fields

Logger (Flogger)

Hytale uses Google's Flogger library, NOT standard Java logging. The syntax is different:

1// WRONG - Standard Java logging syntax
2getLogger().info("Player joined"); // Error!
3getLogger().warning("Something went wrong"); // Error!
4
5// CORRECT - Flogger syntax
6import java.util.logging.Level;
7
8getLogger().at(Level.INFO).log("Player joined");
9getLogger().at(Level.WARNING).log("Something went wrong");
10getLogger().at(Level.SEVERE).log("Critical error!");
11
12// With formatting
13getLogger().at(Level.INFO).log("Player %s joined", player.getName());
common mistake
If you see getLogger().info() in examples, it's wrong. Always use getLogger().at(Level.INFO).log().

Debugging Tips

add logging
Use getLogger().at(Level.INFO).log() liberally to trace execution flow.
check server console
Exceptions are logged to the server console - always check it.
isolate the problem
Comment out code sections to find which part causes issues.
test threading
If something "doesn't work" but has no errors, it's probably threading.

Getting Help

When asking for help, provide:

  • Full stack trace (if any)
  • Relevant code snippets
  • What you expected vs what happened
  • Server version
  • Steps to reproduce
Most problems are solved by reading this documentation carefully. Search for your error message in the docs before asking.