{"record":{"id":"5f5eac49e5c5ee13","repo":"wavetermdev/waveterm","slug":"failed-to-get-stderr-pipe-w","errorCode":null,"errorMessage":"failed to get stderr pipe: %w","messagePattern":"failed to get stderr pipe: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/genconn/genconn.go","lineNumber":78,"sourceCode":"\t// these are not required to be called, if they are not called, the impl will set to discard output\n\tStdinPipe() (io.WriteCloser, error)\n\tStdoutPipe() (io.Reader, error)\n\tStderrPipe() (io.Reader, error)\n}\n\nfunc RunSimpleCommand(ctx context.Context, client ShellClient, spec CommandSpec) (string, string, error) {\n\tproc, err := client.MakeProcessController(spec)\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to create process controller: %w\", err)\n\t}\n\n\tstdout, err := proc.StdoutPipe()\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to get stdout pipe: %w\", err)\n\t}\n\tstderr, err := proc.StderrPipe()\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to get stderr pipe: %w\", err)\n\t}\n\n\tif err := proc.Start(); err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to start process: %w\", err)\n\t}\n\n\tstdoutBuf := syncbuf.MakeSyncBuffer()\n\tstderrBuf := syncbuf.MakeSyncBuffer()\n\tvar wg sync.WaitGroup\n\twg.Add(2)\n\n\tgo func() {\n\t\tdefer wg.Done()\n\t\tio.Copy(stdoutBuf, stdout)\n\t}()\n\n\tgo func() {\n\t\tdefer wg.Done()","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/genconn/genconn.go#L60-L96","documentation":"RunSimpleCommand calls proc.StderrPipe() to capture the child's stderr; this error wraps a failure of that call, after stdout was successfully piped. Same family as the stdout-pipe error: it means output capture could not be set up, typically because the underlying session/exec object is in the wrong state (already started or closed), and the command is aborted before Start().","triggerScenarios":"proc.StderrPipe() returns an error: SSH session already started or closed, controller implementation rejected a second pipe request, or internal pipe allocation failure on the exec.Cmd.","commonSituations":"Custom controller implementations that limit pipe calls to once or start the process prematurely; SSH sessions that timed out between pipe setup calls; extremely fd-constrained systems failing to allocate pipes.","solutions":["Verify the controller implementation allows both StdoutPipe and StderrPipe before Start(), and does not start early.","Inspect the wrapped error for 'session already started' or 'use of closed connection' and fix the ordering / reconnect accordingly.","Check file descriptor limits (ulimit -n) if pipe allocation fails under load.","Create a fresh controller per command run instead of reusing one.","If the SSH connection is stale, reconnect and retry the command."],"exampleFix":"// before\nstderr, err := proc.StderrPipe()\nif err != nil {\n    return \"\", \"\", err\n}\n// after\nstderr, err := proc.StderrPipe()\nif err != nil {\n    if isSessionClosed(err) {\n        if rerr := conn.Reconnect(ctx); rerr == nil {\n            proc, err = client.MakeProcessController(spec)\n            if err == nil {\n                return retryRun(ctx, client, spec)\n            }\n        }\n    }\n    return \"\", \"\", err\n}","handlingStrategy":"try-catch","validationCode":"// take both pipes before starting:\nstdout, err := proc.StdoutPipe()\nif err != nil { return err }\nstderr, err := proc.StderrPipe()\nif err != nil { return err }","typeGuard":null,"tryCatchPattern":"stderr, err := proc.StderrPipe()\nif err != nil {\n    log.Printf(\"stderr pipe failed (stdout ok): %v\", err)\n    // fallback: proceed with discard if stderr capture is optional\n    stderr = io.Discard\n}","preventionTips":["Set up stdout and stderr pipes back-to-back before Start()","Only claim each pipe once per process","Handle fd exhaustion: raise ulimit -n on busy hosts","Reconnect stale SSH sessions before spawning","Prefer genconn.RunSimpleCommand over manual pipe orchestration"],"tags":["process","pipe","ssh","stderr"],"backgroundTag":"process-spawn-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}