Skip to content

fix(MahoganyHomes): guard null home and player location in walkToHome and bank (0.0.15) - #649

Merged
chsami merged 1 commit into
developmentfrom
claude/err-mahoganyhomes-walktohome-null-home-and-location
Oct 17, 2026
Merged

chsami merged 1 commit into
developmentfrom
claude/err-mahoganyhomes-walktohome-null-home-and-location

Conversation

@chsami

@chsami chsami commented Oct 17, 2026

Copy link
Copy Markdown
Owner

Problem

Client error telemetry shows two NullPointerExceptions thrown from MahoganyHomesScript.walkToHome, logged as "Mahogany Homes script loop failed" (plugin 0.0.13, Microbot 2.6.33):

  • Group 2514 (TotalCount 2, ReportCount 1): NullPointerException: Cannot invoke "WorldPoint.getX()" because "point" is null at MahoganyHomesPlugin.distanceBetween:833 <- MahoganyHomesScript.walkToHome:616
  • Group 2517 (TotalCount 1, ReportCount 1): NullPointerException: Cannot invoke "Home.getRequiredPlanks..." at MahoganyHomesScript.planksNeeded:629 <- isMissingItems:624 <- walkToHome:617

Root cause

  • 2514: walkToHome (and bank()) pass Rs2Player.getWorldLocation() directly into distanceBetween, which dereferences the point. The location is null while the game is loading, hopping or logging out. The run loop checks for null at the top, but the value can turn null later in the same tick.
  • 2517: walkToHome and bank() null-check a local copy of currentHome, but isMissingItems -> planksNeeded/steelBarsNeeded and the walk target read plugin.getCurrentHome() again. The client thread clears that field with applyCurrentHome(null) when a contract finishes or is cleared, so the second read can return null.

Change

MahoganyHomesScript.java:

  • New package-private helper isAwayFromHome(Home, WorldPoint). It returns home != null && playerLocation != null && distanceBetween(...) > 0.
  • bank() and walkToHome() each read the home and the player location once and pass them to this helper.
  • isMissingItems, planksNeeded and steelBarsNeeded now take the Home as a parameter. Every call passes the local copy, and walkToHome walks to currentHome.getLocation().

MahoganyHomesPlugin.java: version 0.0.14 -> 0.0.15.

Validation

  • ./gradlew test --tests '*MahoganyHomesScriptTest' --tests '*PluginManifestVersionTest' -PpluginList=MahoganyHomesPlugin -> BUILD SUCCESSFUL
    • MahoganyHomesScriptTest: 4 tests (2 new), 0 failures. The new tests check that a null home or null location gives false, and that a point outside Home.JESS counts as away while a point inside its area on another plane does not.
    • PluginManifestVersionTest: 1 test, 0 failures.
  • Reviewed: both groups fixed at the root.

Known gaps

  • The unit tests cover the null and distance logic in isAwayFromHome. They do not cover the cross-thread race behind group 2517. That race is fixed by reading the home once and passing it down.
  • The same re-read pattern is still present in readyFurniture (null check, then the lambda reads getCurrentHome() again), getFixableObjects, fix() and finish(). readyFurniture is also the stop condition of walkWithStateUntil in walkToHome. None of the reported stack traces go through these paths. A follow-up could read the home once there too.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV

… and bank (0.0.15)

walkToHome and bank null-checked a local copy of the current home but then
re-read plugin.getCurrentHome() through isMissingItems, planksNeeded and
steelBarsNeeded and for the walk target, so a contract cleared on the client
thread mid-loop threw an NPE. Rs2Player.getWorldLocation() was also passed to
distanceBetween unchecked. Snapshot both once, guard them in isAwayFromHome,
and pass the Home through to the material helpers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV
@chsami
chsami merged commit 95d4b7d into development Oct 17, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant