{"record":{"id":"9d1bc5b405e51760","repo":"egametang/ET","slug":"bag-is-full","errorCode":null,"errorMessage":"bag is full","messagePattern":"bag is full","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.item/Scripts/Hotfix/Server/ItemHelper.cs","lineNumber":80,"sourceCode":"                        item.AddCount(addCount);\n                        remainCount -= addCount;\n                        updatedItemIds.Add(item.Id);\n\n                        if (remainCount <= 0)\n                        {\n                            break;\n                        }\n                    }\n                }\n            }\n\n            // 需要创建新物品\n            while (remainCount > 0)\n            {\n                int slotIndex = self.FindEmptySlot();\n                if (slotIndex < 0)\n                {\n                    throw new Exception(\"bag is full\");\n                }\n\n                int addCount = System.Math.Min(remainCount, maxStack);\n                Item newItem = self.AddChild<Item>();\n                newItem.ConfigId = configId;\n                newItem.Count = addCount;\n\n                self.SetSlotItem(slotIndex, newItem);\n                updatedItemIds.Add(newItem.Id);\n                remainCount -= addCount;\n            }\n\n            // 通知客户端物品更新\n            foreach (long itemId in updatedItemIds)\n            {\n                Item item = self.GetItemById(itemId);\n                if (item != null)\n                {","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.item/Scripts/Hotfix/Server/ItemHelper.cs#L62-L98","documentation":"Thrown by ItemHelper.AddItem when FindEmptySlot() returns -1, meaning no empty slot remains after stacking into existing partial stacks. The bag is full and the remaining count cannot be placed, so the operation aborts. Note this throw happens mid-operation, AFTER some items may already have been stacked/created and client notifications partially sent — partial state is a real concern.","triggerScenarios":"AddItem requests more of an item than can fit: stacking exhausts remainCount incompletely, then the while-loop calls FindEmptySlot and gets -1. Triggered when GetUsedSlotCount >= Capacity and the item cannot be fully stacked onto existing slots.","commonSituations":"Granting a large reward into a nearly-full bag; non-stackable items (MaxStack <= 1) with no free slots; a design that doesn't pre-check capacity before granting.","solutions":["Pre-check available space: estimate slots needed (ceil(remainCount / maxStack) minus partial-stack room) and compare against free slots before calling AddItem.","Use IsFull()/GetUsedSlotCount() to refuse the grant upstream and return an error code to the caller.","Make AddItem transactional: snapshot state, and on 'bag is full' roll back any partial stacks/items already created so the bag isn't left half-modified."],"exampleFix":"// before\nItemHelper.AddItem(comp, configId, count, reason); // may throw mid-way\n\n// after — pre-check free space\nint free = comp.Capacity - comp.GetUsedSlotCount();\nif (comp.IsFull()) { /* return ERR_BagFull */ return; }\nItemHelper.AddItem(comp, configId, Math.Min(count, /*slotsNeeded*/), reason);","handlingStrategy":"validation","validationCode":"public static bool CanAddItem(ItemComponent self, int configId, int count)\n{\n    var cat = self.Fiber().GetSingleton<ItemConfigCategory>();\n    var cfg = cat.Get(configId);\n    if (cfg == null) return false;\n    int maxStack = cfg.MaxStack > 1 ? cfg.MaxStack : 1;\n    // free slots available\n    int free = self.Capacity - self.GetUsedSlotCount();\n    // approximate: each free slot holds maxStack; ignore partial-stack room for a conservative check\n    return free * maxStack >= count;\n}\n// usage\nif (!CanAddItem(comp, configId, count)) { /* return ERR_BagFull */ }","typeGuard":null,"tryCatchPattern":"try { ItemHelper.AddItem(comp, configId, count, reason); }\ncatch (Exception e) when (e.Message.Contains(\"bag is full\"))\n{ /* return error code to caller; note partial state risk */ }","preventionTips":["Pre-check free space before granting.","Make AddItem transactional so partial adds roll back on 'bag full'.","For non-stackable items, treat each unit as needing its own slot."],"tags":["item","server","add-item","bag-full","capacity"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}