{"record":{"id":"a85418e179c562d9","repo":"wavetermdev/waveterm","slug":"failed-to-create-stdout-pipe-w","errorCode":null,"errorMessage":"failed to create stdout pipe: %w","messagePattern":"failed to create stdout pipe: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/blockcontroller/tsunamicontroller.go","lineNumber":313,"sourceCode":"func runTsunamiAppBinary(ctx context.Context, appBinPath string, appPath string, blockMeta waveobj.MetaMapType) (*TsunamiAppProc, error) {\n\tcmd := exec.Command(appBinPath)\n\tcmd.Env = append(os.Environ(), \"TSUNAMI_CLOSEONSTDIN=1\")\n\n\tif wavebase.IsDevMode() {\n\t\tcmd.Env = append(cmd.Env, \"TSUNAMI_CORS=\"+tsunamiutil.DevModeCorsOrigins)\n\t}\n\n\t// Add TsunamiEnv variables if configured\n\ttsunamiEnv := blockMeta.GetMap(waveobj.MetaKey_TsunamiEnv)\n\tfor key, value := range tsunamiEnv {\n\t\tif strValue, ok := value.(string); ok {\n\t\t\tcmd.Env = append(cmd.Env, key+\"=\"+strValue)\n\t\t}\n\t}\n\n\tstdoutPipe, err := cmd.StdoutPipe()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create stdout pipe: %w\", err)\n\t}\n\n\tstderrPipe, err := cmd.StderrPipe()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create stderr pipe: %w\", err)\n\t}\n\n\tstdinPipe, err := cmd.StdinPipe()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create stdin pipe: %w\", err)\n\t}\n\n\tappName := build.GetAppName(appPath)\n\n\tlineBuffer := utilds.MakeMultiReaderLineBuffer(1000)\n\tportChan := make(chan int, 1)\n\tportFound := false\n","sourceCodeStart":295,"sourceCodeEnd":331,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/blockcontroller/tsunamicontroller.go#L295-L331","documentation":"cmd.StdoutPipe() on the tsunami app process failed, so the controller cannot stream the app's stdout (needed to detect its 'listening' port message). Almost always indicates os.Pipe resource exhaustion.","triggerScenarios":"runTsunamiAppBinary calls cmd.StdoutPipe() and receives a non-nil error, typically EMFILE (too many open files).","commonSituations":"Long-running Wave session leaking file descriptors; system-wide fd limit (ulimit -n) reached.","solutions":["Raise the file-descriptor limit (ulimit -n)","Restart the app/Wave process to release leaked fds","Check for fd leaks in controllers that never close pipes","Retry starting the block after closing unused blocks"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// check headroom: fds in use vs limit\nf, _ := os.Open(\"/proc/self/status\") // verify FDSize/open fds on Linux","typeGuard":null,"tryCatchPattern":"proc, err := runTsunamiAppBinary(ctx, bin, app, meta)\nif err != nil && strings.Contains(err.Error(), \"failed to create stdout pipe\") {\n\t// free fds / raise ulimit, then retry\n}","preventionTips":["Keep ulimit -n high (e.g. 10240) for the Wave process","Close idle blocks to release pipes","Audit controllers for unclosed pipe leaks"],"tags":["pipe","process","file-descriptors"],"backgroundTag":"fd-exhaustion","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}