Skip to content

fix(inventory): return false from combine when an item is missing - #2252

Merged
chsami merged 1 commit into
developmentfrom
claude/err-rs2inventory-combine-null-item-npe
Nov 12, 2026
Merged

chsami merged 1 commit into
developmentfrom
claude/err-rs2inventory-combine-null-item-npe

Conversation

@chsami

@chsami chsami commented Nov 12, 2026

Copy link
Copy Markdown
Owner

Problem

Rs2Inventory.combine throws a NullPointerException when one of the two items is not in the inventory.

  • Source: client error telemetry, group id 5191
  • Counts: 2 events from 1 report, first and last seen 2026-11-12, client version 2.6.55
  • Exception: java.lang.NullPointerException (Cannot invoke "...Rs2ItemMod...", message cut off by telemetry)
  • Stack: Rs2Inventory.lambda$combine$2:173 <- Rs2Inventory.get:747 <- Rs2Inventory.combine:173 <- Rs2Inventory.combine:137, called from a third-party plugin on its script thread

In the reported case the primary item had already been selected with use(primaryItem) before the lookup of the missing secondary item threw, so besides the uncaught exception the item was left selected with the Use cursor active.

Root cause

combine(int, int) and combine(String, String) pass the result of get(...) straight into combine(Rs2ItemModel, Rs2ItemModel). get(...) returns null for an item that is not in the inventory, and the model overload dereferenced both primary and secondary inside its filter lambdas without a null check.

Change

  • Rs2Inventory.combine(Rs2ItemModel, Rs2ItemModel) returns false at the top when either argument is null, before use(primaryItem), so nothing is left selected. Both delegating overloads are covered by the same guard. Returning false matches the existing Javadoc contract and the existing not-found paths.
  • New Rs2InventoryCombineTest with three cases: by id with the secondary missing, by id with the primary missing, by name with the secondary missing. Each asserts false and that use(...) is never called.
  • docs/entity-guides/items.md: gotcha 21 describing the null-item case, as the repo AGENTS.md asks for when fixing an entity-assumption bug under util/.

Validation

./gradlew :client:runUnitTests --tests "*Rs2InventoryCombineTest" --tests "*Rs2InventoryInvokeMenuTest": BUILD SUCCESSFUL, Rs2InventoryCombineTest 3/3 passed, Rs2InventoryInvokeMenuTest 4/4 passed.

Code review approved the commit. Siblings checked in review: combineClosest overloads already return false on empty lists, use(Rs2ItemModel) already null-guards, and the Rs2Fletching callers all go through the guarded function.

Known gaps

  • The new tests were not run against the unfixed code; that they fail without the fix is judged by reading only.
  • The full unit test suite was not run, only the two focused test classes.
  • Not tested in a live client.
  • The null path returns false without a log line, while the two neighbouring not-found paths log.
  • Pre-existing and not changed here: when both arguments are non-null but no second distinct slot exists (for example the same item id with only one copy in the inventory), the primary is still selected and the method returns false with the Use cursor left active. Follow-up candidate: resolve the secondary item before calling use(primaryItem).

🤖 Generated with Claude Code

Rs2Inventory.combine(int, int) and combine(String, String) pass the
result of get(...) to combine(Rs2ItemModel, Rs2ItemModel), which
dereferenced both arguments. A missing item threw a
NullPointerException on the script thread, and a missing secondary
item left the primary item selected. Return false before any click
when either item is null.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

Rs2Inventory.combine now returns false when either item argument is null, before inventory lookups or interactions. Regression tests cover missing items in ID-based and name-based combination. The documentation describes null handling and advises checking for null before clicking.

Merge Risk: Minimal · up to 2ec88

Combining with a missing inventory item now returns false instead of throwing, and the primary item is no longer left selected in that case. The change is small and has regression tests and documentation, so merge risk is minimal.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title names the main change: Rs2Inventory.combine now returns false when an item is missing. The title matches the changeset summary, the linked objectives, and the PR description. It is concise a…
Description check Passed The description states the NullPointerException in Rs2Inventory.combine, the root cause in combine(int, int) and combine(String, String), and the fix that returns false before use(primaryItem). It als…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title names the main change: Rs2Inventory.combine now returns false when an item is missing. The title matches the changeset summary, the linked objectives, and the PR description. It is concise and uses the conventional fix(scope) form.

Full details: Description check

Explanation

The description states the NullPointerException in Rs2Inventory.combine, the root cause in combine(int, int) and combine(String, String), and the fix that returns false before use(primaryItem). It also lists the new tests, the docs gotcha, validation steps, and known gaps. It is directly related to the changeset.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d70b8314-eeb7-4472-96f9-bf84adfb69f2
Commits

Reviewing files that changed from the base of the PR and between d63ce6a and 2ec886f.

Files selected for processing: 3

  • docs/entity-guides/items.md
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/inventory/Rs2Inventory.java
  • runelite-client/src/test/java/net/runelite/client/plugins/microbot/util/inventory/Rs2InventoryCombineTest.java

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.

@chsami
chsami merged commit 7fd5a00 into development Nov 12, 2026
3 checks 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