{"record":{"id":"553b8d516deb2ba5","repo":"wtfutil/wtf","slug":"invalid-app-index-selected","errorCode":null,"errorMessage":"invalid app index selected","messagePattern":"invalid app index selected","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/app_manager.go","lineNumber":43,"sourceCode":"\n// MakeNewWtfApp creates and starts a new instance of WtfApp from a set of configuration params\nfunc (appMan *WtfAppManager) MakeNewWtfApp(config *config.Config, configFilePath string) {\n\twtfApp := NewWtfApp(tview.NewApplication(), config, configFilePath)\n\tappMan.Add(wtfApp)\n\n\twtfApp.Start()\n}\n\n// Add adds a WtfApp to the collection of apps that the AppManager manages.\n// This app is then available for display onscreen.\nfunc (appMan *WtfAppManager) Add(wtfApp *WtfApp) {\n\tappMan.WtfApps = append(appMan.WtfApps, wtfApp)\n}\n\n// Current returns the currently-displaying instance of WtfApp\nfunc (appMan *WtfAppManager) Current() (*WtfApp, error) {\n\tif appMan.selected < 0 || appMan.selected >= len(appMan.WtfApps) {\n\t\treturn nil, errors.New(\"invalid app index selected\")\n\t}\n\n\treturn appMan.WtfApps[appMan.selected], nil\n}\n\n// Next cycles the WtfApps forward by one, making the next one in the list\n// the current one. If there are none after the current one, it wraps around.\nfunc (appMan *WtfAppManager) Next() (*WtfApp, error) {\n\tappMan.selected++\n\n\tif appMan.selected >= len(appMan.WtfApps) {\n\t\tappMan.selected = 0\n\t}\n\n\treturn appMan.Current()\n}\n\n// Prev cycles the WtfApps backwards by one, making the previous one in the","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/wtfutil/wtf/blob/bb838c1ccb0f0f3223690df44afdec663d622881/app/app_manager.go#L25-L61","documentation":"WtfAppManager.Current() returns this error when the internal 'selected' cursor is out of bounds for the WtfApps slice (negative or >= slice length). It guards every app lookup used for rendering, so a bad index means the manager has no valid app to display. Next/Prev manipulate 'selected', and this error surfaces if cycling or initialization left it invalid.","triggerScenarios":"Calling Current() before any WtfApps were added (selected stays -1 on an empty manager); an implementation of Next/Prev that wraps around without clamping; code that sets appMan.selected manually to a value beyond the slice length; apps being removed without re-clamping selected.","commonSituations":"Booting wtfutil with no apps configured so the manager is empty; a custom module or fork that cycles apps incorrectly; tests constructing a bare WtfAppManager{} and calling Current/Next/Prev without appending apps.","solutions":["Check that at least one app was added to WtfApps before calling Current()","Initialize/validate appMan.selected (default it to 0 after appending the first app)","Fix or guard Next/Prev so wrapping arithmetic cannot leave selected < 0 or >= len(WtfApps)","Handle the returned error by falling back to a default app instead of rendering nil"],"exampleFix":"// before\nappMan.selected = (appMan.selected + 1) % appMan.count // panics on count==0\n// after\nif len(appMan.WtfApps) == 0 {\n    return errors.New(\"no apps configured\")\n}\nappMan.selected = (appMan.selected + 1) % len(appMan.WtfApps)","handlingStrategy":"validation","validationCode":"if mgr == nil || len(mgr.WtfApps) == 0 {\n    return errors.New(\"no apps to display\")\n}\napp, err := mgr.Current()","typeGuard":"func hasApps(mgr *cfg.WtfAppManager) bool {\n    return mgr != nil && len(mgr.WtfApps) > 0\n}","tryCatchPattern":"app, err := mgr.Current()\nif err != nil {\n    log.Printf(\"app manager empty or invalid index: %v\", err)\n    return\n}","preventionTips":["Always append at least one app before cycling","Reset/clamp selected after removing apps","Write a test that calls Next/Prev on an empty manager","Treat Current()'s error as \"no apps configured\", not a crash"],"tags":["go","index-out-of-range","state"],"backgroundTag":"index-out-of-range","analyzedSha":"bb838c1ccb0f0f3223690df44afdec663d622881","analyzedAt":"2026-09-03T17:02:45.030Z","contentChangedAt":"2026-09-03T17:02:45.030Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}