{"record":{"id":"107fab95f6f1e2f8","repo":"dotnet/machinelearning","slug":"index-should-be-non-negative-got-idx","errorCode":null,"errorMessage":"Index should be non-negative, got {idx}.","messagePattern":"Index should be non-negative, got (.+?)\\.","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.ML.Tokenizers/Model/EnglishRobertaTokenizer.cs","lineNumber":1210,"sourceCode":"\n            return idx;\n        }\n\n        public int AddMaskSymbol(string mask = \"<mask>\")\n        {\n            MaskWord = mask;\n            MaskIndex = ReserveStringSymbolSlot(mask, 1);\n            return MaskIndex;\n        }\n\n        /// <exception cref=\"ArgumentOutOfRangeException\">`idx` is negative.</exception>\n        public int this[int idx]\n        {\n            get\n            {\n                if (idx < 0)\n                {\n                    throw new ArgumentOutOfRangeException(nameof(idx), $\"Index should be non-negative, got {idx}.\");\n                }\n\n                return idx < _symbols.Count ? _symbols[idx].Id : UnkIndex;\n            }\n        }\n\n        public int Count => _symbols.Count;\n\n        public bool Equals(HighestOccurrenceMapping other) => _idToIndex.SequenceEqual(other._idToIndex);\n\n        public bool Contains(string symbol) => symbol != null && _stringSymbolToIndexMapping.ContainsKey(symbol);\n\n        public bool Contains(int id) => _idToIndex.ContainsKey(id);\n\n        /// <exception cref=\"ArgumentNullException\">`symbol` is `null`.</exception>\n        public int IndexOf(int id) => _idToIndex.ContainsKey(id) ? _idToIndex[id] : UnkIndex;\n\n        /// <summary>","sourceCodeStart":1192,"sourceCodeEnd":1228,"githubUrl":"https://github.com/dotnet/machinelearning/blob/7b76e69cf964daeca3f1377af6bc5543284d56c6/src/Microsoft.ML.Tokenizers/Model/EnglishRobertaTokenizer.cs#L1192-L1228","documentation":"The Symbols indexer returns the token ID at a given index, or UnkIndex for out-of-range (but non-negative) indices; a negative index is invalid and throws ArgumentOutOfRangeException with the offending value in the message.","triggerScenarios":"Indexing tokenizer.Symbols (or the RobertaSymbol collection) with a negative int, typically from a lookup that returned -1 as 'not found' and the result being used as an index.","commonSituations":"Using a TryGetValue-style result of -1 as an index; arithmetic like lastIndex-1 when the collection is empty; mapping a vocab lookup miss (-1) directly into the symbol table.","solutions":["Check the index is >= 0 before indexing; treat negative values as 'token not found' and use the unknown token ID instead.","Fix the lookup that produced the negative value to use TryGetValue semantics rather than a -1 sentinel.","Note: out-of-range non-negative indices already fall back to UnkIndex, so only negativity needs guarding."],"exampleFix":"// before\nint id = tokenizer.Symbols[lookupResult]; // lookupResult may be -1\n// after\nint id = lookupResult >= 0 ? tokenizer.Symbols[lookupResult] : tokenizer.Symbols[tokenizer.UnknownTokenId]; // or UnkIndex fallback","handlingStrategy":"type-guard","validationCode":"if (index < 0) throw new InvalidOperationException(\"Symbol index must be non-negative\");\nint id = tokenizer.Symbols[index];","typeGuard":"bool TryGetSymbolId(System.Collections.Generic.IReadOnlyList<int> lookup, string token, out int id)\n{ id = lookup.TryGetValue(token, out var idx) && idx >= 0 ? idx : -1; return id >= 0; }","tryCatchPattern":"try { id = symbols[index]; }\ncatch (ArgumentOutOfRangeException ex) when (ex.ParamName == \"idx\") { id = unkIndex; log($\"Negative symbol index {ex.ActualValue}\"); }","preventionTips":["Treat -1 from lookups as 'not found', never as an index.","Convert lookup-miss sentinels to explicit unknown-token IDs before indexing.","Guard downstream arithmetic (e.g., idx-1 on possibly-empty results).","Remember non-negative out-of-range indices safely return UnkIndex; only negativity throws."],"tags":["argument-validation","indexing","tokenizer","csharp"],"backgroundTag":"argument-out-of-range","analyzedSha":"7b76e69cf964daeca3f1377af6bc5543284d56c6","analyzedAt":"2026-09-11T12:35:38.930Z","contentChangedAt":"2026-09-11T12:35:38.930Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}