wavetermdev/waveterm · error

error statting cwd %q: %w

Error message

error statting cwd %q: %w

What it means

checkCwd calls os.Stat(cwd) to confirm the working directory exists and is accessible. If Stat fails (missing directory, permission denied, or path pointing to a file), the error is wrapped as "error statting cwd %q: %w" including the offending path. This prevents the pty spawn from failing deep inside exec with a confusing error.

Source

Thrown at pkg/shellexec/shellexec.go:115

func ExitCodeFromWaitErr(err error) int {
	if err == nil {
		return 0
	}
	if exitErr, ok := err.(*exec.ExitError); ok {
		if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
			return status.ExitStatus()
		}
	}
	return -1

}

func checkCwd(cwd string) error {
	if cwd == "" {
		return fmt.Errorf("cwd is empty")
	}
	if _, err := os.Stat(cwd); err != nil {
		return fmt.Errorf("error statting cwd %q: %w", cwd, err)
	}
	return nil
}

type PipePty struct {
	remoteStdinWrite *os.File
	remoteStdoutRead *os.File
}

func (pp *PipePty) Fd() uintptr {
	return pp.remoteStdinWrite.Fd()
}

func (pp *PipePty) Name() string {
	return "pipe-pty"
}

func (pp *PipePty) Read(p []byte) (n int, err error) {

View on GitHub (pinned to a4447c1563)

Solutions

  1. os.Stat the cwd before starting the process and fall back to home directory if invalid
  2. Restore/recreate the missing directory or fix permissions (chmod/chown)
  3. Update the block's saved cwd to an existing path
  4. If the path moved, migrate the stored cwd value

Example fix

// before
proc, err := shellexec.StartLocalShellProc(ctx, termSize, cmdStr, cmdOpts, savedCwd)
// after
if _, err := os.Stat(savedCwd); err != nil {
    savedCwd, _ = os.UserHomeDir()
}
proc, err := shellexec.StartLocalShellProc(ctx, termSize, cmdStr, cmdOpts, savedCwd)
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(cwd)
if err != nil || !info.IsDir() {
    cwd, _ = os.UserHomeDir() // fallback to a directory that exists
}

Try / catch

proc, err := shellexec.StartLocalShellProc(ctx, termSize, cmdStr, cmdOpts, cwd)
if err != nil && strings.HasPrefix(err.Error(), "error statting cwd") {
    cwd, _ = os.UserHomeDir()
    proc, err = shellexec.StartLocalShellProc(ctx, termSize, cmdStr, cmdOpts, cwd)
}

Prevention

When it happens

Trigger: StartLocalShellProc invoked with a cwd path that no longer exists (deleted directory), is a file instead of a directory, or is not readable due to permissions.

Common situations: User deleted or renamed the directory a block was running in; NFS/network mount offline; SSH remote whose directory vanished; cwd stored from a previous session on a different machine.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/3c54cd48ceb637e2. Report an issue: GitHub.