{"record":{"id":"998f070a20a4188e","repo":"tui-cs/Terminal.Gui","slug":"must-be-non-negative","errorCode":null,"errorMessage":"Must be non-negative","messagePattern":"Must be non-negative","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"Terminal.Gui/Views/CollectionNavigation/CollectionNavigatorBase.cs","lineNumber":42,"sourceCode":"        {\n            lock (_lock)\n            {\n                _searchString = value;\n            }\n\n            OnSearchStringChanged (new (value));\n        }\n    }\n\n    /// <inheritdoc/>\n    public int TypingDelay { get; set; } = 500;\n\n    /// <inheritdoc/>\n    public int? GetNextMatchingItem (int? currentIndex, char keyStruck)\n    {\n        if (currentIndex.HasValue && currentIndex < 0)\n        {\n            throw new ArgumentOutOfRangeException (nameof (currentIndex), @\"Must be non-negative\");\n        }\n\n        if (!char.IsControl (keyStruck))\n        {\n            // maybe user pressed 'd' and now presses 'd' again.\n            // a candidate search is things that begin with \"dd\"\n            // but if we find none then we must fallback on cycling\n            // d instead and discard the candidate state\n            var candidateState = \"\";\n            TimeSpan elapsedTime;\n            string currentSearchString;\n\n            lock (_lock)\n            {\n                elapsedTime = DateTime.Now - _lastKeystroke;\n                currentSearchString = _searchString;\n            }\n","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/tui-cs/Terminal.Gui/blob/2e47b11478db083499917f2ad27c34d30efb0df1/Terminal.Gui/Views/CollectionNavigation/CollectionNavigatorBase.cs#L24-L60","documentation":"GetNextMatchingItem performs type-ahead navigation in a list/table/tree. The currentIndex parameter represents the currently selected item index; a negative value is invalid because there is no item at a negative position. Pass null when there is no current selection.","triggerScenarios":"Calling navigator.GetNextMatchingItem(-1, 'a'); or passing a computed currentIndex that went negative (e.g. SelectedItem - 1 when SelectedItem was 0).","commonSituations":"Off-by-one in selection math; passing -1 as a 'no selection' sentinel instead of null; decrementing an index below zero before calling.","solutions":["Pass null instead of -1 when there is no current selection.","Clamp the index to >= 0 before calling.","Check HasValue and >= 0 before invoking."],"exampleFix":"// before\nnavigator.GetNextMatchingItem(list.SelectedItem - 1, key);\n// after\nnavigator.GetNextMatchingItem(list.SelectedItem > 0 ? list.SelectedItem - 1 : null, key);","handlingStrategy":"validation","validationCode":"int? idx = current < 0 ? null : current;\nnavigator.GetNextMatchingItem (idx, key);","typeGuard":"static bool IsValidNavIndex (int? i) => i is null || i >= 0;","tryCatchPattern":null,"preventionTips":["Pass null for 'no selection', not -1.","Clamp decremented indices to >= 0.","Check HasValue before passing."],"tags":["navigation","collection","index","validation"],"backgroundTag":null,"analyzedSha":"2e47b11478db083499917f2ad27c34d30efb0df1","analyzedAt":"2026-08-13T19:20:08.826Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}