{"record":{"id":"cb9af73e0b0c5df5","repo":"charmbracelet/bubbletea","slug":"bubbletea-could-not-create-cancelable-reader-w","errorCode":null,"errorMessage":"bubbletea: could not create cancelable reader: %w","messagePattern":"bubbletea: could not create cancelable reader: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tty.go","lineNumber":71,"sourceCode":"}\n\n// initInputReader (re)commences reading inputs.\nfunc (p *Program) initInputReader(cancel bool) error {\n\tif cancel && p.cancelReader != nil {\n\t\tp.cancelReader.Cancel()\n\t\tp.waitForReadLoop()\n\t}\n\n\tterm := p.environ.Getenv(\"TERM\")\n\n\t// Initialize the input reader.\n\t// This need to be done after the terminal has been initialized and set to\n\t// raw mode.\n\n\tvar err error\n\tp.cancelReader, err = uv.NewCancelReader(p.input)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"bubbletea: could not create cancelable reader: %w\", err)\n\t}\n\n\tdrv := uv.NewTerminalReader(p.cancelReader, term)\n\tdrv.SetLogger(p.logger)\n\tp.inputScanner = drv\n\tp.readLoopDone = make(chan struct{})\n\n\tgo p.readLoop()\n\n\treturn nil\n}\n\nfunc (p *Program) readLoop() {\n\tdefer close(p.readLoopDone)\n\n\tif err := p.inputScanner.StreamEvents(p.ctx, p.msgs); err != nil {\n\t\tselect {\n\t\tcase <-p.ctx.Done():","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/charmbracelet/bubbletea/blob/351d2159f8d8a85613aa2a6e98c8c63df3c98623/tty.go#L53-L89","documentation":"Returned by initInputReader when uv.NewCancelReader(p.input) fails — Bubble Tea could not construct a cancellable reader over the configured input, which it needs so the read loop can be stopped on shutdown. On Unix this allocates an epoll-based cancelreader; on unsupported or constrained environments construction fails and Program.Run aborts right after terminal setup.","triggerScenarios":"Input fd not pollable (regular files, some /dev/null setups, closed fds on platforms where cancelreader needs a valid pollable fd); ulimit exhaustion (EMFILE) preventing epoll/fd creation; exotic Unixes lacking the required syscalls; certain container/seccomp profiles blocking epoll_create.","commonSituations":"tea.WithInput fed a regular file or bytes.Buffer on platforms where the cancelreader needs extra fds; very high fd counts hitting limits; hardened containers blocking epoll; older kernels/sandboxed environments (gVisor quirks).","solutions":["Use tea.WithInput(bytes.NewReader(...)) style readers only where supported, or wrap scripted input differently (feed via p.Send instead of a fake reader)","Raise fd limits (ulimit -n) if EMFILE","In seccomp-restricted containers, allow epoll syscalls or run with tea.WithInput(nil)","Report platform-specific construction failures upstream with the wrapped error"],"exampleFix":"// before\np := tea.NewProgram(m, tea.WithInput(bytes.NewBufferString(\"q\")))\n_, err := p.Run() // cancelreader construction may fail on this platform\n\n// after\np := tea.NewProgram(m, tea.WithInput(nil))\ngo func() {\n    time.Sleep(500 * time.Millisecond)\n    p.Send(key.NewMsg(key.WithKeys(\"q\"))) // script input as messages\n}()\n_, err := p.Run()","handlingStrategy":"fallback","validationCode":"// Probe cancelreader viability cheaply: if construction fails, fall back\n// to message-driven input:\nfunc inputReaderOK(r io.Reader) bool {\n    cr, err := cancelreader.NewReader(r)\n    if err != nil { return false }\n    _ = cr.Close()\n    return true\n}","typeGuard":"func isCancelReaderFailure(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"could not create cancelable reader\")\n}","tryCatchPattern":"_, err := p.Run()\nif isCancelReaderFailure(err) {\n    // fallback: no reader, drive via Send()\n    p2 := tea.NewProgram(m, tea.WithInput(nil))\n    go func() { p2.Send(key.NewMsg(key.WithKeys(\"q\"))) }()\n    _, err = p2.Run()\n}\nif err != nil { log.Fatal(err) }","preventionTips":["For scripted input prefer p.Send with key messages over fake readers on fragile platforms","Raise RLIMIT_NOFILE in fd-hungry daemons","Allow epoll in container seccomp profiles","Pin a recent bubbletea/cancelreader version for platform fixes"],"tags":["bubbletea","cancelreader","epoll","fd-limits","platform","go"],"backgroundTag":null,"analyzedSha":"351d2159f8d8a85613aa2a6e98c8c63df3c98623","analyzedAt":"2026-08-15T10:48:22.366Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}