{"record":{"id":"04399f2c46b21a5f","repo":"wavetermdev/waveterm","slug":"cwd-is-empty","errorCode":null,"errorMessage":"cwd is empty","messagePattern":"cwd is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/shellexec/shellexec.go","lineNumber":112,"sourceCode":"\t}\n}\n\nfunc ExitCodeFromWaitErr(err error) int {\n\tif err == nil {\n\t\treturn 0\n\t}\n\tif exitErr, ok := err.(*exec.ExitError); ok {\n\t\tif status, ok := exitErr.Sys().(syscall.WaitStatus); ok {\n\t\t\treturn status.ExitStatus()\n\t\t}\n\t}\n\treturn -1\n\n}\n\nfunc checkCwd(cwd string) error {\n\tif cwd == \"\" {\n\t\treturn fmt.Errorf(\"cwd is empty\")\n\t}\n\tif _, err := os.Stat(cwd); err != nil {\n\t\treturn fmt.Errorf(\"error statting cwd %q: %w\", cwd, err)\n\t}\n\treturn nil\n}\n\ntype PipePty struct {\n\tremoteStdinWrite *os.File\n\tremoteStdoutRead *os.File\n}\n\nfunc (pp *PipePty) Fd() uintptr {\n\treturn pp.remoteStdinWrite.Fd()\n}\n\nfunc (pp *PipePty) Name() string {\n\treturn \"pipe-pty\"","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/shellexec/shellexec.go#L94-L130","documentation":"checkCwd validates the working directory before spawning a local shell process. If the cwd string is empty, it returns \"cwd is empty\" without attempting any I/O. This guards cmd.Dir from being set to an invalid empty value and failing later in exec.","triggerScenarios":"Calling StartLocalShellProc with a block controller / shell state whose cwd field is unset (empty string), e.g. a block created without a valid working directory.","commonSituations":"Block state missing cwd because the connection config never resolved a home directory, a fresh install where home is unset, or the shell state was cleared.","solutions":["Set a valid cwd before starting the shell (default to os.UserHomeDir() or \"/\")","Ensure the block controller's state carries a non-empty cwd","Fix connection/workspace config so cwd resolves to the user's home"],"exampleFix":"// before\nproc, err := shellexec.StartLocalShellProc(ctx, termSize, cmdStr, cmdOpts, \"\")\n// after\ncwd := state.Cwd\nif cwd == \"\" {\n    home, herr := os.UserHomeDir()\n    if herr != nil { home = \"/\" }\n    cwd = home\n}\nproc, err := shellexec.StartLocalShellProc(ctx, termSize, cmdStr, cmdOpts, cwd)","handlingStrategy":"validation","validationCode":"func ensureCwd(cwd string) (string, error) {\n    if cwd == \"\" {\n        home, err := os.UserHomeDir()\n        if err != nil { return \"\", err }\n        return home, nil\n    }\n    return cwd, nil\n}","typeGuard":null,"tryCatchPattern":"proc, err := shellexec.StartLocalShellProc(ctx, termSize, cmdStr, cmdOpts, cwd)\nif err != nil && strings.Contains(err.Error(), \"cwd is empty\") {\n    cwd, _ = os.UserHomeDir()\n    proc, err = shellexec.StartLocalShellProc(ctx, termSize, cmdStr, cmdOpts, cwd)\n}","preventionTips":["Always initialize block state cwd from the user's home directory","Validate cwd at config-load time, not just at spawn time","Never persist an empty cwd into shell state"],"tags":["go","shell","cwd","validation"],"backgroundTag":"cwd-missing","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}