Skip to content

fix(FarmTreeRun): guard null object composition in isPatchEmpty and handlePatch (1.2.5) - #651

Merged
chsami merged 2 commits into
developmentfrom
claude/err-farmtreerun-is-patch-empty-null-composition
Oct 17, 2026
Merged

chsami merged 2 commits into
developmentfrom
claude/err-farmtreerun-is-patch-empty-null-composition

Conversation

@chsami

@chsami chsami commented Oct 17, 2026

Copy link
Copy Markdown
Owner

Problem

Client error telemetry group 2525 (1 occurrence, 1 report, Microbot 2.6.33, FarmTreeRunPlugin 1.2.2, thread FarmTreeRunScript-3):

java.lang.NullPointerException: Cannot invoke "net.runelite.api.ObjectComposition.getName()" because the return value of ... is null
  at FarmTreeRunScript.isPatchEmpty:1207
  at FarmTreeRunScript.handlePlantingTree:1025
  at FarmTreeRunScript.handlePatch:907
  at FarmTreeRunScript.lambda$run$2:326

The NPE kills the loop iteration right after a sapling is planted.

Root cause

Rs2GameObject.getObjectComposition(int) in the client is @Nullable. It returns null when the client-thread read fails or times out, or when the impostor resolves to null while the patch changes after planting. isPatchEmpty dereferenced the result without a check. handlePatch had the same unguarded pattern on findObjectComposition(treePatch.getId()).getActions().

Change

  • isPatchEmpty: a null composition (or null name) is treated as an empty patch, not an NPE. Every caller goes through this helper.
  • handlePatch: if the tree patch composition or its actions are null, the method returns false and the loop retries on the next tick.
  • handlePayment: the three "protection disabled" early returns no longer call isPatchEmpty. With protection off and PROTECT, the method returns without reading the composition or looking up the gardener. The only PROTECT caller runs only after treePlanted, so caller behaviour is unchanged.
  • Plugin version 1.2.3 -> 1.2.5.

Validation

  • New FarmTreeRunPatchEmptyTest (4 cases) and FarmTreeRunHandlePatchTest (3 cases). The handlePatch/handlePayment cases fail with an NPE against the previous script and pass with this change.
  • ./gradlew test --tests 'net.runelite.client.plugins.microbot.farmtreerun.*' -PpluginList=FarmTreeRunPlugin: all farmtreerun tests pass.
  • ./gradlew build -PpluginList=FarmTreeRunPlugin: BUILD SUCCESSFUL. Full test suite: 148 suites, 918 tests, 0 failures.

Known gaps

  • Not live-tested in game. The null composition is a timing condition that is hard to reproduce on demand.
  • If the composition is briefly null on a patch that is already planted, one compost/sapling use-on-object attempt can go through. The game rejects it harmlessly, and the patch is retried on the next tick.
  • The version goes from 1.2.3 to 1.2.5 within this branch, so 1.2.4 is never published.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV

chsami and others added 2 commits October 17, 2026 19:25
…atchEmpty (1.2.4)

Rs2GameObject.getObjectComposition is nullable and returns null on a
client-thread read timeout or a null impostor while the patch object
transforms after planting, which threw an NPE from handlePlantingTree.
A null composition now reads as an empty patch so the post-plant wait
keeps polling and planting is retried instead of the patch being skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV
… composition read when protection is off (1.2.5)

handlePatch dereferenced Rs2GameObject.findObjectComposition(...).getActions()
without a null check; the composition is null on the same client-thread
read failure or null impostor that caused the isPatchEmpty NPE. Return
false so the loop retries on the next tick.

handlePayment's protection opt-out checks no longer read the patch
composition, so a transient null can no longer fall through to paying
the gardener when protection is disabled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV
@chsami
chsami merged commit 79f3247 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