{"record":{"id":"d414c57a44320201","repo":"egametang/ET","slug":"invalid-slot-index-slotindex-d414c5","errorCode":null,"errorMessage":"invalid slot index: {slotIndex}","messagePattern":"invalid slot index: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.item/Scripts/Hotfix/Server/ItemComponentSystem.cs","lineNumber":200,"sourceCode":"\n        /// <summary>\n        /// 尝试获取指定槽位的物品\n        /// </summary>\n        public static Item TryGetSlotItem(this ItemComponent self, int slotIndex)\n        {\n            if ((uint)slotIndex < (uint)self.SlotItems.Count)\n            {\n                return self.SlotItems[slotIndex];\n            }\n\n            return null;\n        }\n\n        private static void EnsureSlotIndex(ItemComponent self, int slotIndex)\n        {\n            if (slotIndex < 0)\n            {\n                throw new Exception($\"invalid slot index: {slotIndex}\");\n            }\n\n            if (slotIndex >= self.Capacity)\n            {\n                throw new Exception($\"slot index {slotIndex} exceeds capacity {self.Capacity}\");\n            }\n        }\n\n        private static void EnsureSlotContainerSize(ItemComponent self, int size)\n        {\n            if (size <= 0)\n            {\n                return;\n            }\n\n            if (self.SlotItems.Count >= size)\n            {\n                return;","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.item/Scripts/Hotfix/Server/ItemComponentSystem.cs#L182-L218","documentation":"Thrown by the SERVER-side ItemComponentSystem.EnsureSlotIndex when slotIndex < 0. EnsureSlotIndex is the guard inside server SetSlotItem (line 175) and is the first of two checks (negative, then over-capacity). A negative index is always a programming error since valid slots are 0..Capacity-1.","triggerScenarios":"A server caller passes a negative slotIndex to SetSlotItem (e.g. the result of FindEmptySlot == -1 used without checking). FindEmptySlot returns -1 to mean 'no slot', so feeding that straight into SetSlotItem triggers this exact throw.","commonSituations":"Using FindEmptySlot()'s return value without testing for -1; an off-by-one in a loop that decrements past zero; a deserialized SlotIndex that was never initialized (default 0 is fine, but -1 used as an 'empty' marker persists into storage).","solutions":["Always check FindEmptySlot() >= 0 before using the result (see ItemHelper.AddItem line 78 for the correct pattern).","If storing a sentinel for 'no slot', use a nullable int or a separate flag, never -1 in a field that flows into SetSlotItem.","Audit server code that constructs slotIndex from arithmetic and clamp at >= 0."],"exampleFix":"// before\nint slot = component.FindEmptySlot();\ncomponent.SetSlotItem(slot, item); // slot may be -1\n\n// after\nint slot = component.FindEmptySlot();\nif (slot < 0) { /* handle full bag */ return; }\ncomponent.SetSlotItem(slot, item);","handlingStrategy":"validation","validationCode":"int slot = component.FindEmptySlot();\nif (slot < 0) { /* bag full or no slot */ return; }\ncomponent.SetSlotItem(slot, item);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always check FindEmptySlot() >= 0 before using the result.","Don't store -1 in a SlotIndex field; use a separate 'empty' flag.","Centralize slot allocation through one helper that validates."],"tags":["item","server","slot-index","validation"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}