larksuite/cli · error
failed to read input: %w
Error message
failed to read input: %w
What it means
`lark-cli config init` legacy interactive mode reads each answer with bufio.Reader.ReadString('\n'). If reading fails with a non-EOF error (I/O failure on stdin), the error is wrapped as "failed to read input". An EOF with an empty line produces the distinct "input terminated unexpectedly (EOF)" error instead.
Source
Thrown at cmd/config/init.go:502
}
// Non-terminal: cannot run interactive mode, guide user to --new
if !f.IOStreams.IsTerminal {
return errs.NewValidationError(errs.SubtypeInvalidArgument, "config init requires a terminal for interactive mode. Run with --new to create a new app:\n lark-cli config init --new\nThis command blocks until setup is complete and outputs a verification URL. Run it in the background, then retrieve the URL from its output.")
}
// Mode 5: Legacy interactive (readline fallback)
firstApp := (*core.AppConfig)(nil)
if existing != nil {
firstApp = existing.CurrentAppConfig("")
}
reader := bufio.NewReader(f.IOStreams.In)
readLine := func(prompt string) (string, error) {
fmt.Fprintf(f.IOStreams.ErrOut, "%s: ", prompt)
line, err := reader.ReadString('\n')
if err != nil && err != io.EOF {
return "", fmt.Errorf("failed to read input: %w", err)
}
if err == io.EOF && strings.TrimSpace(line) == "" {
return "", fmt.Errorf("input terminated unexpectedly (EOF)")
}
return strings.TrimSpace(line), nil
}
prompt := "App ID"
if firstApp != nil && firstApp.AppId != "" {
prompt += fmt.Sprintf(" [%s]", firstApp.AppId)
}
appIdInput, err := readLine(prompt)
if err != nil {
return errs.NewValidationError(errs.SubtypeInvalidArgument, "%s", err).WithCause(err)
}
prompt = "App Secret"
if firstApp != nil && !firstApp.AppSecret.IsZero() {View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Run the command in a real interactive terminal so stdin is open and readable.
- If scripting, use the non-interactive path: `lark-cli config init --new`, or provide config via flags/env instead of piping answers.
- Check for and fix wrappers/CI steps that close or redirect stdin (e.g. `< /dev/null`), or use `script -c` / a pseudo-TTY if interaction is unavoidable.
Example fix
// before: piping answers into an interactive command fails on stdin $ echo "cli_x\nsecret" | lark-cli config init // after: use the non-interactive creation path $ lark-cli config init --new # blocks until setup completes, prints verification URL
Defensive patterns
Strategy: fallback
Validate before calling
// Guard before running interactive init
if !term.IsTerminal(int(os.Stdin.Fd())) {
return errors.New("config init requires a TTY; run with --new for non-interactive setup")
} Try / catch
if err := runConfigInit(); err != nil {
if strings.Contains(err.Error(), "failed to read input") {
// fall back to non-interactive creation
return runConfigInitNew()
}
return err
} Prevention
- Never pipe stdin into interactive commands; use --new or flags.
- In CI, check for a TTY before invoking interactive commands.
- Avoid wrappers that close stdin; use `script -c` if a pseudo-TTY is required.
- Keep terminal sessions attached during the blocking setup flow.
When it happens
Trigger: Running config init when the stdin read fails at the OS level: stdin closed by the shell, a broken pipe from a scripted invocation, device errors, or the input stream being reset mid-prompt.
Common situations: Invoking the interactive command inside CI or a non-interactive shell where stdin is /dev/null or a closed fd; a parent process killing the pipe; running under a wrapper that does not allocate a TTY.
Related errors
- input terminated unexpectedly (EOF)
- failed to read stdin: %w
- please select at least one domain
- stdin is empty (did you forget to pipe input?)
- invalid chart size: {size!r}
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/2446ccb013636274.
Report an issue: GitHub.