Minecraft Scripting API

Please note: Some examples on this page may be outdated or may not work as expected.

Troubleshooting & Debugging

Common issues and how to solve them.

Debugging Mindset

When something doesn't work, the first instinct is "the API is broken" or "this shouldn't work this way". Usually it's a small detail - wrong event name, forgot to subscribe, typo. Use logging (console.log) to understand what's actually happening.

Script Not Loading

Problem: Your add-on doesn't run or errors appear

Error: Failed to load script

Solutions:

  1. Check manifest.json has correct entry point
  2. Verify script file is in correct folder
  3. Enable world logging to see errors
  4. Check console for syntax errors
// Add debug logging to track execution
console.log("Script loading..."); // Add at top of file

world.afterEvents.worldInitialize.subscribe(() => {
  console.log("World initialized - script is working!");
});

Events Not Firing

Problem: Player events or block events aren't triggering

Common mistake: Using the wrong object. Events are on world, not on the player or block:

// Wrong - won't work (players don't have event subscriptions)
player.afterEvents.playerJoin.subscribe(() => {
  console.log("Player joined");
});

// Correct - use world (server-wide events)
world.afterEvents.playerJoin.subscribe((event) => {
  console.log("Player joined: " + event.player.nameTag);
});

Why? world is the server object that tracks everything. Individual players don't emit events - the world does.

Permission Errors

Problem: "Player lacks permission" error

Error: Entity does not have permission to run command

Solution: Check player permissions in world settings

  • Creator mode disabled → Limited permissions
  • Enable Creator mode or use alternative methods
  • Don't use commands in survival mode scripts
// Instead of runCommand, use direct API
// Wrong:
player.runCommand("say hello");

// Right:
player.sendMessage("hello");

Null Reference Errors

Problem: "Cannot read property of undefined"

This happens when you assume something exists but it doesn't:

// Wrong - crashes if no players online (getAllPlayers returns empty array)
const player = world.getAllPlayers()[0];
player.sendMessage("Hello"); // ERROR: player is undefined

// Right - check first
const players = world.getAllPlayers();
if (players.length > 0) {
  players[0].sendMessage("Hello");
}

// Or use optional chaining (?.  skips if null)
world.getAllPlayers()[0]?.sendMessage("Hello");

Why? Always assume things might be null. An empty query, a deleted entity, a player who left - these happen. Defensive coding prevents crashes.

Performance Issues

Problem: Game lags when script runs

// Bad - runs every tick on all players
world.afterEvents.entityTick.subscribe((event) => {
  if (event.entity.typeId === "minecraft:player") {
    // Heavy computation here
    calculateComplexPath(event.entity);
  }
});

// Better - use intervals instead
let lastCheck = 0;
const checkInterval = 1000; // 1 second

world.afterEvents.entityTick.subscribe((event) => {
  const now = Date.now();
  if (event.entity.typeId === "minecraft:player" && 
      now - lastCheck > checkInterval) {
    lastCheck = now;
    calculateComplexPath(event.entity);
  }
});

Data Not Saving

Problem: SuperDB data disappears

// Make sure to save data
const playerDB = new SuperDB({ name: "players", immediateWrite: true });

// Wrong - data not saved
const player = playerDB.get("player_id");
player.level = 10; // Changed but not saved!

// Right - save after changes
const player = playerDB.get("player_id");
player.level = 10;
playerDB.set("player_id", player); // Save it

Item Not Appearing

Problem: Items given to players don't show up

// Wrong - wrong syntax
const item = new ItemStack("diamond_sword");
player.addItem(item);

// Right - use container
const item = new ItemStack("diamond_sword", 1);
player.container.addItem(item);

// Check if inventory is full
const success = player.container.addItem(item);
if (!success) {
  player.sendMessage("§cYour inventory is full!");
}

Command System Issues

Problem: Custom chat commands not working

// Make sure to cancel the event
world.beforeEvents.chatSend.subscribe((event) => {
  if (event.message.startsWith("!help")) {
    // Without this, command shows in chat
    event.cancel = true;
    
    event.sender.sendMessage("§6=== Help ===");
  }
});

Block Breaking Not Prevented

Problem: Can't prevent players from breaking blocks

// Wrong - doesn't work
world.afterEvents.blockBreak.subscribe((event) => {
  event.cancel = true; // This event can't be canceled
});

// Right - restore the block
world.afterEvents.blockBreak.subscribe((event) => {
  const block = event.block;
  const player = event.player;
  
  if (block.typeId === "minecraft:obsidian") {
    // Restore the block
    world.getDimension("overworld").setBlockType(
      block.location,
      "minecraft:obsidian"
    );
    player.sendMessage("§cYou cannot break obsidian!");
  }
});

Teleport Not Working

Problem: Players won't teleport

// Make sure player has update tick
world.afterEvents.playerSpawn.subscribe((event) => {
  const player = event.player;
  
  // Teleport after a tick to ensure chunks are loaded
  system.run(() => {
    player.teleport({ x: 0, y: 64, z: 0 });
  });
});

Memory Leaks

Problem: Game slows down over time

// Bad - interval never stops
const interval = setInterval(() => {
  // Code here
}, 1000);

// Good - stop when needed
const intervals = [];

function startMonitoring() {
  const id = setInterval(() => {
    // Code here
  }, 1000);
  intervals.push(id);
}

function stopMonitoring() {
  intervals.forEach(id => clearInterval(id));
  intervals.length = 0;
}

// Or use system.run for one-time execution
system.run(() => {
  // Runs once per tick, no memory leak
});

Debugging Tips

Add logging everywhere:

console.log("Starting script");
console.log("Player joined: " + player.nameTag);
console.log("Current level: " + playerData.level);

Check types:

console.log(typeof entity); // "object"
console.log(entity.typeId); // "minecraft:player"
console.log(entity instanceof Entity); // true/false

Use conditional logging:

const DEBUG = true;

if (DEBUG) {
  console.log("Debug info: " + value);
}

Test in isolation:

// Test just your function
function testDamageCalculation() {
  const damage = calculateDamage(10, 2);
  console.log("Damage: " + damage);
  // Should log: Damage: 20
}

testDamageCalculation();
Navigation