Investigate backpacks rejecting item insertion after restart
Investigate player reports on 2026-10-19 that backpacks no longer accept items after restart. Confirmed on Ithaca: all four PFEs running 17c9f9076 log MoveItemToBagMessage decoding EndOfStreamException at line 26, before the inventory handler. Root cause: settings-sync PR #2729 (2099d7136) bounds inbound readers to header Size, excluding alignment padding; the existing decoder incorrectly requires three trailing bytes after its 25-byte core body. Previous receive parsing exposed padding/next packet bytes and hid this mismatch. No persisted-item corruption demonstrated. Local implementation on fix/backpack-packet-decoding: make the three-byte legacy trailer optional only when the required core body has ended; preserve existing longer serializer format and reject truncated core fields/partial legacy trailers. No transfer/ownership/capacity checks or receive-framing code changed. Validation: new tests reproduced three failures before the fix, including the exact production exception. After the fix, all 140 selected networking, bag-handler and item-move tests pass in an isolated .NET 10 SDK container. Coverage includes short core body, legacy serialization, every core truncation, partial trailers, padded/unpadded packets split at every byte boundary followed by another message. Dependent engines build during test run; git diff --check passes. Existing unrelated test-project warnings remain. Committed and pushed as 973a73728 on fix/backpack-packet-decoding after fast-forwarding to develop 11f8d696d. Clean rebuild and focused validation on the updated base: 141 passed, zero failures/skips. No deployment, production restart or real-client post-fix smoke performed. Acceptance: reproduce failure, preserve item safety checks and pass relevant tests/builds (verified); live bag insertion after deploying the corrected decoder remains outstanding. Follow-up report at 09:53: mission floor-item pickup is also failing. Read-only Ithaca log sampling confirms PickUpFixtureMessage EndOfStreamException at constructor line 22 (first trailing byte) and CreateQuestMessage EndOfStreamException at line 29 (first trailing byte). Both decoders require the same three-byte trailer after their 17-byte core body, matching the bag regression mechanism. PR #2731 merged as 22cdcb7a7 and fixes bags. Follow-up implemented on fix/mission-packet-decoding from origin/develop 22cdcb7a7: PickUpFixtureMessage and CreateQuestMessage now accept their 17-byte core body without padding, while preserving legacy three-byte trailer decoding and rejecting truncations. Six new cases reproduced the exact production exceptions before correction. After correction, 167 selected networking, pickup-handler/serialization, bag-handler, item-move and mission-persistence tests pass with no failures/skips. Tests exercise both message types with/without legacy trailers, every required-field truncation and partial trailer, and padded/unpadded framing at every TCP split followed by another packet. Dependent engines build and git diff --check passes. Follow-up committed and pushed as 63dd04e37. Pull request #2733 — https://git.project-rk.com/prk/engines/pulls/2733 (fix/mission-packet-decoding → develop). No deployment or real-client post-fix smoke performed. Other sampled errors (SessionInfo, CharDCMove, GenericCmd and Trade) are handler errors, not demonstrated padding/decoding regressions. Follow-up framing investigation: scoped parallel static review of commit 2099d7136 and directly relevant inbound dependencies completed with partial coverage; it found one additional medium-severity correctness issue in Session.cs SettlePadding (~line 705). When both current and padding-shifted bytes resemble headers, it always prefers the shifted interpretation and discards genuine bytes from supported unpadded traffic. Executed reproduction in /tmp/prk-bag-decoding-validation only: an unpadded 70-byte message followed by a real TextMessage serializer output (sender 0x0014002A, text 'hello world') causes a disconnect and loses the text, both in whole-message and one-byte-fragmented delivery (2 failing tests). No production occurrence established; current GameConnection pads messages, so this finding concerns supported unpadded mode and header-value collisions. Proposed next step: strengthen competing-header discrimination and add this reproduction to repository regression coverage. No repository edits for this investigation; scratch reproduction remains outside the repo. Review scope excludes unrelated preferences-sync logic and is not an exhaustive project audit. Read-only production sample during investigation: PFEs/Login still reported image 17c9f9076; no additional decoder-error classes beyond the three corrected messages in the sampled recent logs. SessionInfo handler null-reference errors continue (SessionInfoMessageHandler line 27), but causality to framing is unproven. Log sampling is bounded by --tail and does not establish complete post-deploy health. Pull request: #2731 — https://git.project-rk.com/prk/engines/pulls/2731 (fix/backpack-packet-decoding → develop). Client-binary verification and canonical cleanup (user requested): imported the available AO client directory with neighboring dependencies into the persistent Ghidra container before analysis. Gamecode.dll ClientContainerAddItemIIR_t writer 0x10015151 writes exactly two identities; ClientGetItemIIR_t writer 0x1001523c and CreateQuestIIR_t writer 0x100cab36 each write exactly one identity. N3.dll n3InfoItemRemote_t::Write at 0x100098f4 writes the type, actor identity, one pass-on byte, and the virtual subclass payload with no trailer. N3 MapToKey at 0x10009826 XORs string bytes into 4 byte lanes; reproducing it confirms the three class names map to 0x1f4d5f7e, 0x37136c6b and 0x291f361b respectively. Canonical declared sizes including 20-byte typed header: bag move 45; pickup and mission acceptance 37. No live packet capture claimed. Analyzed binary SHA256: Gamecode.dll 2c349e73675e258cce58ce81fc2cd51d7c994b70e310e64d56059864f85a9201; N3.dll c71d97f3050565780cfc47e3c1969acec7b3ca2182497ecf50342e2ab9c2637f. Ghidra analysis exported to /data/inbox/Gamecode-packet-writers.gzf and /data/inbox/N3-packet-writers.gzf; container stopped after analysis to free memory. Implemented canonical cleanup on fix/canonical-item-mission-packets from develop 3f509f1a1: remove fake trailing properties, reads and writes from all three messages; update headless-client initializer and client/server tests. Bounded readers consume only required core fields, so older locally generated packets with extra declared bytes still decode without assigning meaning to trailers. Fixtures assert exact independently specified core bytes and declared sizes, preserve required-field truncation rejection, and test canonical/legacy framing with/without transport padding at every TCP split boundary. Twelve fixture/consumption assertions failed before correction. Validation after correction: 180 focused engine/network/pickup/item/mission tests and 120 focused client mission/inventory interaction tests pass, no failures/skips; dependent client and engine builds succeed; git diff --check passes. Initial parallel build timed out before tests; reduced-parallelism rerun passed after freeing Ghidra memory. Committed and pushed as a36d82da8. Pull request #2735 — https://git.project-rk.com/prk/engines/pulls/2735 (fix/canonical-item-mission-packets → develop). Changes remain undeployed. The separate optional-padding header-ambiguity bug is not changed by this cleanup.
Checklist
0 of 0 completeNo checklist items.
- Area
- Project Rubi-Ka
- Project
- engines
- Kind
- Bug
- Priority
- High
- Task ID
tsk_zevdthumnf- Updated