{"record":{"id":"29042337b3f50d6f","repo":"egametang/ET","slug":"item-cannot-be-null","errorCode":null,"errorMessage":"Item cannot be null","messagePattern":"Item cannot be null","errorType":"validation","errorClass":"System.Exception","httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.equipment/Scripts/Hotfix/Server/EquipmentComponentSystem.cs","lineNumber":34,"sourceCode":"\n        [EntitySystem]\n        private static void Destroy(this EquipmentComponent self)\n        {\n            self.EquippedItems.Clear();\n        }\n\n        #endregion\n\n        #region 业务方法\n\n        /// <summary>\n        /// 穿戴装备（将Item从背包移到装备槽位）\n        /// </summary>\n        public static void EquipItem(this EquipmentComponent self, Item item, EquipmentSlotType slotType)\n        {\n            if (item == null)\n            {\n                throw new System.Exception(\"Item cannot be null\");\n            }\n\n            self.AddChild(item);\n\n            // 检查Item是否有装备组件\n            item.AddComponent<EquipmentItemComponent>();\n\n\n            // 如果该槽位已有装备，先卸下\n            if (self.EquippedItems.ContainsKey(slotType))\n            {\n                Item oldItem = self.EquippedItems[slotType];\n                if (oldItem != null)\n                {\n                    // 卸下旧装备，设置SlotIndex为-1表示未装备\n                    oldItem.SlotIndex = -1;\n                }\n            }","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.equipment/Scripts/Hotfix/Server/EquipmentComponentSystem.cs#L16-L52","documentation":"Explicit ArgumentNullException-style guard in EquipmentComponentSystem.EquipItem (line 34): EquipItem throws 'Item cannot be null' when the caller passes a null Item. This is a programming-contract failure in the caller, not a runtime data problem - the equipment component never received a valid item to slot.","triggerScenarios":"Calling equipmentComp.EquipItem(null, slotType), e.g. after a lookup that returned null (item not found in bag, already-removed item, EntityRef that was disposed), or passing an item before it was created/loaded.","commonSituations":"UI equip button wired to a null selected item, inventory lookup miss fed straight to EquipItem, using an Item after RemoveFromParent/dispose, race where item is freed mid-request.","solutions":["Null-check the item at the call site before EquipItem and bail/log instead of throwing.","Fix the upstream lookup so it never yields null (or handle the not-found case).","Guard EntityRef dereferences before treating them as valid Items.","Add an audit of the equip flow to confirm item lifecycle."],"exampleFix":"// before\ncomp.EquipItem(bag.GetItem(id), slot);\n\n// after\nItem item = bag.GetItem(id);\nif (item == null) { Log.Warning($\"equip: item {id} not found\"); return; }\ncomp.EquipItem(item, slot);","handlingStrategy":"validation","validationCode":"if (item == null) throw new ArgumentNullException(nameof(item));","typeGuard":"static bool CanEquip(Item item) => item != null && item.Parent == null; // not already parented","tryCatchPattern":null,"preventionTips":["Null-check Items from any lookup before equipping.","Treat EntityRef derefs as nullable.","Validate item is not disposed/already-parented."],"tags":["gameplay","null-safety","validation"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}