{"record":{"id":"3c83959101b94525","repo":"charmbracelet/gum","slug":"unable-to-read-stdin","errorCode":null,"errorMessage":"unable to read stdin","messagePattern":"unable to read stdin","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pager/command.go","lineNumber":23,"sourceCode":"\t\"regexp\"\n\n\t\"charm.land/bubbles/v2/help\"\n\t\"charm.land/bubbles/v2/viewport\"\n\ttea \"charm.land/bubbletea/v2\"\n\t\"charm.land/gum/v2/internal/stdin\"\n\t\"charm.land/gum/v2/internal/timeout\"\n)\n\n// Run provides a shell script interface for the viewport bubble.\n// https://github.com/charmbracelet/bubbles/viewport\nfunc (o Options) Run() error {\n\tvp := viewport.New(viewport.WithWidth(o.Style.Width), viewport.WithHeight(o.Style.Height))\n\tvp.Style = o.Style.ToLipgloss()\n\n\tif o.Content == \"\" {\n\t\tstdin, err := stdin.Read()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"unable to read stdin\")\n\t\t}\n\t\tif stdin != \"\" {\n\t\t\t// Sanitize the input from stdin by removing backspace sequences.\n\t\t\tbackspace := regexp.MustCompile(\".\\x08\")\n\t\t\to.Content = backspace.ReplaceAllString(stdin, \"\")\n\t\t} else {\n\t\t\treturn fmt.Errorf(\"provide some content to display\")\n\t\t}\n\t}\n\n\tm := model{\n\t\tviewport:            vp,\n\t\thelp:                help.New(),\n\t\tcontent:             o.Content,\n\t\torigContent:         o.Content,\n\t\tshowLineNumbers:     o.ShowLineNumbers,\n\t\tlineNumberStyle:     o.LineNumberStyle.ToLipgloss(),\n\t\tsoftWrap:            o.SoftWrap,","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/charmbracelet/gum/blob/4d089f95507708a71f64dacfe7ca513219dd5267/pager/command.go#L5-L41","documentation":"Returned by the pager command's Run when stdin.Read fails and o.Content is empty. Note the original error is discarded — the pager reports only that stdin could not be read, so the underlying cause (e.g. 'stdin is empty') is hidden. The pager requires either explicit Content or readable piped stdin.","triggerScenarios":"Running the pager with no --content and no piped stdin (stdin is a TTY or empty pipe): e.g. `gum pager` run interactively without `< file`.","commonSituations":"Invoking the pager in a script without redirecting input; upstream pipeline stage produced nothing; running under a scheduler where stdin is /dev/null.","solutions":["Pipe content into the pager: `cat file | gum pager` or `gum pager < file`","Pass content explicitly via the pager options instead of relying on stdin","Check the upstream pipeline stage emits non-empty output","In Go callers, check stdin.Read's error before constructing pager Options and log its cause"],"exampleFix":"// before\n// no input: gum pager  -> \"unable to read stdin\"\n// after\ngum pager < README.md\n# or programmatically\ncontent, err := stdin.Read()\nif err != nil { return fmt.Errorf(\"unable to read stdin: %w\", err) }","handlingStrategy":"validation","validationCode":"fi, _ := os.Stdin.Stat()\nif (fi.Mode() & os.ModeCharDevice) != 0 { return fmt.Errorf(\"pager needs input: pipe a file or set content\") }","typeGuard":"func stdinHasData() bool {\n    fi, err := os.Stdin.Stat()\n    return err == nil && (fi.Mode()&os.ModeCharDevice) == 0 && fi.Size() != 0\n}","tryCatchPattern":"err := pagerCmd.Run()\nif err != nil && err.Error() == \"unable to read stdin\" {\n    return fmt.Errorf(\"no pager content: pipe input or pass content explicitly\")\n}","preventionTips":["Always pipe input or set content explicitly for the pager","Verify upstream pipeline output is non-empty","Wrap stdin.Read errors with %w so causes aren't discarded (library-side fix)","Pre-check stdin is not a TTY before invoking"],"tags":["go","stdin","pager","empty-input"],"backgroundTag":"stdin-empty","analyzedSha":"4d089f95507708a71f64dacfe7ca513219dd5267","analyzedAt":"2026-08-31T18:45:06.436Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}