{"record":{"id":"3a6fd0bbec809609","repo":"wavetermdev/waveterm","slug":"failed-to-read-jwt-token-from-stdin-w","errorCode":null,"errorMessage":"failed to read JWT token from stdin: %w","messagePattern":"failed to read JWT token from stdin: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/wsh/cmd/wshcmd-connserver.go","lineNumber":434,"sourceCode":"\tselect {} // run forever\n}\n\nfunc askForJwtToken() (string, error) {\n\t// if it already exists in the environment, great, use it\n\tjwtToken := os.Getenv(wavebase.WaveJwtTokenVarName)\n\tif jwtToken != \"\" {\n\t\tfmt.Printf(\"HAVE-JWT\\n\")\n\t\treturn jwtToken, nil\n\t}\n\n\t// otherwise, ask for it\n\tfmt.Printf(\"%s\\n\", wavebase.NeedJwtConst)\n\n\t// read a single line from stdin\n\tvar line string\n\t_, err := fmt.Fscanln(os.Stdin, &line)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to read JWT token from stdin: %w\", err)\n\t}\n\treturn strings.TrimSpace(line), nil\n}\n\nfunc serverRun(cmd *cobra.Command, args []string) error {\n\tconnServerInitialEnv = envutil.PruneInitialEnv(envutil.SliceToMap(os.Environ()))\n\n\tvar logFile *os.File\n\tif connServerDev {\n\t\tvar err error\n\t\tlogFilePath := fmt.Sprintf(\"/tmp/waveterm-connserver-%d.log\", os.Getuid())\n\t\tlogFile, err = os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)\n\t\tif err != nil {\n\t\t\tfmt.Fprintf(os.Stderr, \"failed to open log file: %v\\n\", err)\n\t\t\tlog.SetFlags(log.LstdFlags | log.Lmicroseconds)\n\t\t\tlog.SetPrefix(fmt.Sprintf(\"[PID:%d] \", os.Getpid()))\n\t\t} else {\n\t\t\tdefer logFile.Close()","sourceCodeStart":416,"sourceCodeEnd":452,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/cmd/wsh/cmd/wshcmd-connserver.go#L416-L452","documentation":"When wsh connserver is not given a JWT on the command line, askForJwtToken reads one line from stdin with fmt.Fscanln. If stdin is closed, empty, or unreadable, it wraps the failure in this error and server startup aborts.","triggerScenarios":"wsh connserver runs without --jwt and stdin is at EOF (e.g. spawned with no stdin, </dev/null, or from a daemon/service with no attached stdin), or Fscanln fails on an empty line.","commonSituations":"Running the command in a CI job or systemd unit where stdin is /dev/null; piping nothing into the command; launching it from a GUI/parent process that does not forward stdin; pressing Ctrl-D immediately at the prompt.","solutions":["Pass the token explicitly via the --jwt flag so stdin is not needed","Pipe the token in: echo \"<jwt>\" | wsh connserver ...","Ensure the launching process provides a working stdin pipe","Check that the parent process (e.g. Wave client) actually writes the token before closing the pipe"],"exampleFix":"// before\nwsh connserver --conn myserver < /dev/null\n// after\nwsh connserver --conn myserver --jwt \"$WAVETERM_JWT\"\n// or: echo \"$WAVETERM_JWT\" | wsh connserver --conn myserver","handlingStrategy":"fallback","validationCode":"// before spawning, ensure stdin is a readable pipe/file:\nfi, _ := os.Stdin.Stat()\nstdinUsable := fi != nil && (fi.Mode()&os.ModeCharDevice) == 0 || fi != nil","typeGuard":null,"tryCatchPattern":"line, err := readJwtFromStdin()\nif err != nil {\n\treturn fmt.Errorf(\"no JWT on stdin: %w (pass --jwt or pipe the token)\", err)\n}","preventionTips":["Prefer the --jwt flag over interactive stdin in scripts/CI","Pipe the token explicitly: echo \"$JWT\" | wsh connserver ...","Ensure service units and daemons provide stdin or avoid stdin-based prompts entirely","Detect EOF early and fail fast with an actionable message"],"tags":["stdin","jwt","cli","io"],"backgroundTag":"stdin-read-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}