wavetermdev/waveterm · error

unknown shell type: %s

Error message

unknown shell type: %s

What it means

DetectShellTypeAndVersionFromPath first classifies the shell via GetShellTypeFromShellPath, which only recognizes bash, zsh, fish, and pwsh/powershell substrings in the basename. If the path matches none (ShellType_unknown), it returns this error with the offending path. Wave cannot manage shells it cannot classify.

Source

Thrown at pkg/util/shellutil/shellutil.go:497

	return ShellType_unknown
}

var (
	bashVersionRegexp = regexp.MustCompile(`\bversion\s+(\d+\.\d+)`)
	zshVersionRegexp  = regexp.MustCompile(`\bzsh\s+(\d+\.\d+)`)
	fishVersionRegexp = regexp.MustCompile(`\bversion\s+(\d+\.\d+)`)
	pwshVersionRegexp = regexp.MustCompile(`(?:PowerShell\s+)?(\d+\.\d+)`)
)

func DetectShellTypeAndVersion() (string, string, error) {
	shellPath := DetectLocalShellPath()
	return DetectShellTypeAndVersionFromPath(shellPath)
}

func DetectShellTypeAndVersionFromPath(shellPath string) (string, string, error) {
	shellType := GetShellTypeFromShellPath(shellPath)
	if shellType == ShellType_unknown {
		return shellType, "", fmt.Errorf("unknown shell type: %s", shellPath)
	}

	shellBase := filepath.Base(shellPath)
	if shellType == ShellType_pwsh && strings.Contains(shellBase, "powershell") && !strings.Contains(shellBase, "pwsh") {
		return "powershell", "", nil
	}

	version, err := getShellVersion(shellPath, shellType)
	if err != nil {
		return shellType, "", err
	}

	return shellType, version, nil
}

func getShellVersion(shellPath string, shellType string) (string, error) {
	ctx, cancelFn := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancelFn()

View on GitHub (pinned to a4447c1563)

Solutions

  1. Set the user's shell to a supported one (bash, zsh, fish, pwsh) via chsh or install pwsh.
  2. Ensure SHELL is exported and points at a real shell binary before running detection.
  3. Create a symlink whose basename contains the shell name (e.g. ln -s nu /usr/local/bin/... only if truly compatible — otherwise switch shells).
  4. If you control the caller, pre-validate the path with GetShellTypeFromShellPath and handle ShellType_unknown gracefully.

Example fix

// before
$ SHELL=/usr/bin/tcsh wave
detect error: unknown shell type: /usr/bin/tcsh
// after
$ chsh -s /bin/zsh && SHELL=/bin/zsh wave
Defensive patterns

Strategy: validation

Validate before calling

// pre-validate the shell path before calling detection
shellPath := os.Getenv("SHELL")
switch {
case strings.Contains(filepath.Base(shellPath), "bash"),
	strings.Contains(filepath.Base(shellPath), "zsh"),
	strings.Contains(filepath.Base(shellPath), "fish"),
	strings.Contains(filepath.Base(shellPath), "pwsh"),
	strings.Contains(filepath.Base(shellPath), "powershell"):
	// supported
default:
	return fmt.Errorf("shell %q not supported; use bash/zsh/fish/pwsh", shellPath)
}

Type guard

func isSupportedShell(shellPath string) bool {
	return shellutil.GetShellTypeFromShellPath(shellPath) != shellutil.ShellType_unknown
}

Try / catch

shellType, version, err := shellutil.DetectShellTypeAndVersionFromPath(shellPath)
if err != nil {
	if strings.HasPrefix(err.Error(), "unknown shell type") {
		return fmt.Errorf("%w; falling back to bash", err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling DetectShellTypeAndVersion (via DetectLocalShellPath) or DetectShellTypeAndVersionFromPath with a path whose basename lacks bash/zsh/fish/pwsh/powershell — e.g. csh, tcsh, nushell, dash, empty path, or a wrapper script named 'myshell'.

Common situations: Users with exotic login shells (tcsh, nu, elvish) set as $SHELL; SHELL env var empty in non-login service contexts; custom-named shell symlinks like /usr/bin/sh POSIX sh.

Related errors


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