wtfutil/wtf · error

invalid app index selected

Error message

invalid app index selected

What it means

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.

Source

Thrown at app/app_manager.go:43

// MakeNewWtfApp creates and starts a new instance of WtfApp from a set of configuration params
func (appMan *WtfAppManager) MakeNewWtfApp(config *config.Config, configFilePath string) {
	wtfApp := NewWtfApp(tview.NewApplication(), config, configFilePath)
	appMan.Add(wtfApp)

	wtfApp.Start()
}

// Add adds a WtfApp to the collection of apps that the AppManager manages.
// This app is then available for display onscreen.
func (appMan *WtfAppManager) Add(wtfApp *WtfApp) {
	appMan.WtfApps = append(appMan.WtfApps, wtfApp)
}

// Current returns the currently-displaying instance of WtfApp
func (appMan *WtfAppManager) Current() (*WtfApp, error) {
	if appMan.selected < 0 || appMan.selected >= len(appMan.WtfApps) {
		return nil, errors.New("invalid app index selected")
	}

	return appMan.WtfApps[appMan.selected], nil
}

// Next cycles the WtfApps forward by one, making the next one in the list
// the current one. If there are none after the current one, it wraps around.
func (appMan *WtfAppManager) Next() (*WtfApp, error) {
	appMan.selected++

	if appMan.selected >= len(appMan.WtfApps) {
		appMan.selected = 0
	}

	return appMan.Current()
}

// Prev cycles the WtfApps backwards by one, making the previous one in the

View on GitHub (pinned to bb838c1ccb)

Solutions

  1. Check that at least one app was added to WtfApps before calling Current()
  2. Initialize/validate appMan.selected (default it to 0 after appending the first app)
  3. Fix or guard Next/Prev so wrapping arithmetic cannot leave selected < 0 or >= len(WtfApps)
  4. Handle the returned error by falling back to a default app instead of rendering nil

Example fix

// before
appMan.selected = (appMan.selected + 1) % appMan.count // panics on count==0
// after
if len(appMan.WtfApps) == 0 {
    return errors.New("no apps configured")
}
appMan.selected = (appMan.selected + 1) % len(appMan.WtfApps)
Defensive patterns

Strategy: validation

Validate before calling

if mgr == nil || len(mgr.WtfApps) == 0 {
    return errors.New("no apps to display")
}
app, err := mgr.Current()

Type guard

func hasApps(mgr *cfg.WtfAppManager) bool {
    return mgr != nil && len(mgr.WtfApps) > 0
}

Try / catch

app, err := mgr.Current()
if err != nil {
    log.Printf("app manager empty or invalid index: %v", err)
    return
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of wtfutil/wtf@bb838c1ccb (2026-09-03). Data as JSON: /api/errors/553b8d516deb2ba5. Report an issue: GitHub.