hypersdk

TUI Crash Fix Summary

Problem

The interactive TUI mode (--interactive) was experiencing a panic immediately after connecting to vSphere and loading VMs.

Error message:

ERROR: application failed | error=TUI error: program was killed: program experienced a panic

Root Causes Found

1. Uninitialized Spinner (CRITICAL)

Location: cmd/hyperexport/main.go:1984-2024 (tuiModel initialization)

Issue: The spinner field in tuiModel struct was not being initialized, but the Init() method was calling m.spinner.Tick at interactive_tui.go:787.

Fix: Added spinner initialization in runInteractiveTUI():

// Initialize spinner
s := spinner.New()
s.Spinner = spinner.Dot
s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("205"))

And added import: "github.com/charmbracelet/bubbles/spinner"

2. Uninitialized Search Input (CRITICAL)

Location: cmd/hyperexport/main.go:1984-2024 (tuiModel initialization)

Issue: The searchInput field (textinput.Model) was not initialized. Would have caused a panic when user pressed “/” to search (at interactive_tui.go:1054).

Fix: Added textinput initialization:

// Initialize search input
si := textinput.New()
si.Placeholder = "Type to search VMs..."
si.CharLimit = 100

And added import: "github.com/charmbracelet/bubbles/textinput"

3. Incorrect Message Type Handling (CRITICAL - ACTUAL PANIC CAUSE)

Location: cmd/hyperexport/interactive_tui.go:944-955

Issue: In the tickMsg handler, the code was incorrectly passing a tickMsg (type time.Time) to m.spinner.Update(msg), but the spinner only accepts spinner.TickMsg. This type mismatch caused a panic.

Original buggy code:

case tickMsg:
    m.animFrame++
    var cmd tea.Cmd
    if m.phase == "export" || m.phase == "validation" || m.phase == "cloudupload" {
        cmd = tickCmd()
    }
    // BUG: passing wrong message type to spinner
    m.spinner, cmd = m.spinner.Update(msg)
    return m, cmd

Fixed code:

case tickMsg:
    m.animFrame++
    if m.phase == "export" || m.phase == "validation" || m.phase == "cloudupload" {
        return m, tickCmd()
    }
    return m, nil

Explanation: The spinner has its own separate tick message handling via spinner.TickMsg (lines 957-960). The custom tickMsg handler should only manage animation frames and phase-specific ticking, not update the spinner.

Files Modified

  1. cmd/hyperexport/main.go
    • Added spinner and textinput imports
    • Initialized spinner component
    • Initialized searchInput component
    • Added both to tuiModel struct initialization
  2. cmd/hyperexport/interactive_tui.go
    • Fixed tickMsg handler to not incorrectly update spinner with wrong message type

Testing Recommendations

  1. Test basic TUI launch: build/hyperexport --interactive
  2. Test search functionality: Press “/” after VMs load
  3. Test during export phases to ensure animation frames work correctly
  4. Test all phases that use spinner (loading, export, validation, cloudupload)

Technical Details

Message Flow

Bubbletea Components Used

Resolution Status

✅ All critical initialization issues resolved ✅ Message type handling corrected ✅ Build successful ✅ Ready for testing