{"record":{"id":"878929e9e7f2f78b","repo":"charmbracelet/bubbletea","slug":"bubbletea-initialmodel-cannot-be-nil","errorCode":null,"errorMessage":"bubbletea: InitialModel cannot be nil","messagePattern":"bubbletea: InitialModel cannot be nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tea.go","lineNumber":993,"sourceCode":"\t_, okSSHTTY := environ.LookupEnv(\"SSH_TTY\")\n\t_, okWTSession := environ.LookupEnv(\"WT_SESSION\")\n\n\treturn (!okTermProg && !okSSHTTY) ||\n\t\tokWTSession ||\n\t\t(okTermProg && !strings.Contains(termProg, \"Apple\") && !okSSHTTY) ||\n\t\tstrings.Contains(termType, \"ghostty\") ||\n\t\tstrings.Contains(termType, \"wezterm\") ||\n\t\tstrings.Contains(termType, \"alacritty\") ||\n\t\tstrings.Contains(termType, \"kitty\") ||\n\t\tstrings.Contains(termType, \"rio\")\n}\n\n// Run initializes the program and runs its event loops, blocking until it gets\n// terminated by either [Program.Quit], [Program.Kill], or its signal handler.\n// Returns the final model.\nfunc (p *Program) Run() (returnModel Model, returnErr error) {\n\tif p.initialModel == nil {\n\t\treturn nil, errors.New(\"bubbletea: InitialModel cannot be nil\")\n\t}\n\n\t// Initialize context and teardown channel.\n\tp.handlers = channelHandlers{}\n\tcmds := make(chan Cmd)\n\n\tp.finished = make(chan struct{})\n\tdefer func() {\n\t\tclose(p.finished)\n\t}()\n\n\tdefer p.cancel()\n\n\tif p.disableInput {\n\t\tp.input = nil\n\t} else if p.input == nil {\n\t\tp.input = os.Stdin\n\t\tif !term.IsTerminal(os.Stdin.Fd()) {","sourceCodeStart":975,"sourceCodeEnd":1011,"githubUrl":"https://github.com/charmbracelet/bubbletea/blob/351d2159f8d8a85613aa2a6e98c8c63df3c98623/tea.go#L975-L1011","documentation":"Program.Run returns this error immediately when the model passed to tea.NewProgram was nil. Bubble Tea requires a non-nil Model to call Init/Update/View on, so this is a fail-fast guard before any terminal setup happens. The program returns p.initialModel (nil) alongside the error and no terminal state is touched.","triggerScenarios":"tea.NewProgram(nil) followed by Run; a constructor function returning a nil *concreteModel typed as tea.Model (typed-nil: non-nil interface holding nil pointer is caught here only if the interface itself is nil); passing a nil model variable because of an uninitialized struct or early-return in a builder.","commonSituations":"Factories like newModel(opts) that return nil on bad options but the caller forgets to check; typed-nil pitfalls where var m *myModel = nil is passed and methods are called on it (panics later instead); refactoring that removes model instantiation; conditional model creation where one branch returns nil.","solutions":["Ensure the model passed to tea.NewProgram is a properly initialized, non-nil value","Check the return of your model constructor before creating the program","If the nil-ness comes from a typed nil pointer, guard for that in your constructor so NewProgram receives a real value","Add a unit test that constructs the program exactly like main() does"],"exampleFix":"// before\nvar m tea.Model // nil\np := tea.NewProgram(m)\n\n// after\nm := newModel() // returns initialized model\np := tea.NewProgram(m)","handlingStrategy":"validation","validationCode":"func newProgram(m tea.Model, opts ...tea.ProgramOption) *tea.Program {\n    if m == nil {\n        log.Fatal(\"model must not be nil\")\n    }\n    return tea.NewProgram(m, opts...)\n}","typeGuard":"func hasModel(m tea.Model) bool {\n    if m == nil { return false }\n    // catch typed-nil pointers of common shapes\n    v := reflect.ValueOf(m)\n    switch v.Kind() {\n    case reflect.Ptr, reflect.Map, reflect.Slice, reflect.Interface:\n        return !v.IsNil()\n    }\n    return true\n}","tryCatchPattern":"_, err := p.Run()\nif err != nil && strings.Contains(err.Error(), \"InitialModel cannot be nil\") {\n    // programmer error: fix call site, don't retry\n    panic(err)\n}","preventionTips":["Construct and validate the model in one place (constructor that never returns nil)","Fail fast in main(): check constructor errors before NewProgram","Beware typed-nil: returning (*myModel)(nil) as tea.Model passes nil-check only at interface level — normalize with a value receiver or explicit nil check","Add a smoke test that builds the program as main does"],"tags":["bubbletea","validation","nil-model","go","programming-error"],"backgroundTag":null,"analyzedSha":"351d2159f8d8a85613aa2a6e98c8c63df3c98623","analyzedAt":"2026-08-15T10:48:22.366Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}