Repository navigation
fix(FarmTreeRun): build bank withdrawal list locally to avoid CME (1.2.3) - #639
Merged
Merged
Conversation
…2.3) bank() iterated the shared items field while the stop path cleared it from the plugin-stop thread, throwing ConcurrentModificationException. The withdrawal list is now a local variable passed to the travel-item helpers, the merge is a static helper, and stopping the script no longer touches it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV
3 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Client error telemetry group 1915 (1 event, 1 reporter, Microbot 2.6.32, FarmTreeRunPlugin 1.2.2, first and last seen 2026-10-15) reports a
java.util.ConcurrentModificationExceptionon threadFarmTreeRunScript-1:Root cause
FarmTreeRunScriptkept a single per-instanceitemslist.bank()iterates it at line 748 (for (FarmingItem item : items)), and every iteration blocks on the client thread throughgetLinkedId(). While that loop runs,shutdown()(called fromFarmTreeRunPlugin.shutDown()on the plugin-stop thread) runsitems.clear()on the same list. A second scheduled loop on the same instance would also have shared the list. Either writer changing the list during the loop throws the CME. The line numbers match origin/development (6f54d34) exactly.Change
itemsfield.bank()now builds a localList<FarmingItem> items = new ArrayList<>(), so nothing is shared across threads.addAvailableTravelItemandaddFirstTravelItemtake that list as their first parameter.static List<FarmingItem> mergeItems(List<FarmingItem>)so it can be unit tested.shutdown()no longer clears the list, because the list no longer exists outsidebank().Validation
FarmTreeRunBankItemsTest:FarmTreeRunScriptdeclares a non-staticCollectionfield again (the removeditemsfield fails it);mergeItemssums entries with the same id and noted flag, keeps noted and unnoted apart, preserves order, and returns a new list without changing the input../gradlew test --tests '*FarmTreeRunBankItemsTest' --tests '*PluginManifestVersionTest' -PpluginList=FarmTreeRunPluginpasses.Known gaps
bank()can still reachRs2Bank.depositAllExceptbefore theisRunning()checks in the withdraw loops. The scheduled future is cancelled on stop, so the impact is low.run()still overwritesmainScheduledFuturewithout cancelling an earlier one. With the list now local, a second loop can no longer cause this CME, so that change was left out.🤖 Generated with Claude Code
https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV