wavetermdev/waveterm · error

open and openExternal cannot both be true

Error message

open and openExternal cannot both be true

What it means

PathCommand (pkg/wshrpc/wshserver/wshserver.go:1413) resolves a Wave directory path (config, data, or log) and can open it either in an internal preview block (Open) or via the OS default handler (OpenExternal). These two open modes are mutually exclusive, so the command rejects requests with both flags set rather than picking one arbitrarily. This is a pure client-side request validation error; no I/O occurs before it.

Source

Thrown at pkg/wshrpc/wshserver/wshserver.go:1428

	return filestore.WFS.WriteFile(ctx, data.ZoneId, data.FileName, []byte(envStr))
}

func (ws *WshServer) PathCommand(ctx context.Context, data wshrpc.PathCommandData) (string, error) {
	pathType := data.PathType
	openInternal := data.Open
	openExternal := data.OpenExternal
	var path string
	switch pathType {
	case "config":
		path = wavebase.GetWaveConfigDir()
	case "data":
		path = wavebase.GetWaveDataDir()
	case "log":
		path = filepath.Join(wavebase.GetWaveDataDir(), "waveapp.log")
	}

	if openInternal && openExternal {
		return "", fmt.Errorf("open and openExternal cannot both be true")
	}

	if openInternal {
		_, err := ws.CreateBlockCommand(ctx, wshrpc.CommandCreateBlockData{
			TabId: data.TabId,
			BlockDef: &waveobj.BlockDef{Meta: map[string]any{
				waveobj.MetaKey_View: "preview",
				waveobj.MetaKey_File: path,
			}},
			Ephemeral: true,
			Focused:   true,
		})

		if err != nil {
			return path, fmt.Errorf("error opening path: %w", err)
		}
	} else if openExternal {
		err := open.Run(path)

View on GitHub (pinned to a4447c1563)

Solutions

  1. Set only one of Open or OpenExternal to true in the PathCommandData before invoking the RPC.
  2. In CLI usage, pass only one of --open or --open-external.
  3. In wrapping code, add a guard that clears OpenExternal when Open is set (or return your own validation error) before calling PathCommand.

Example fix

// before
wshclient.PathCommand(ctx, wshrpc.PathCommandData{PathType: "log", Open: true, OpenExternal: true})
// after
wshclient.PathCommand(ctx, wshrpc.PathCommandData{PathType: "log", Open: true})
Defensive patterns

Strategy: validation

Validate before calling

if data.Open && data.OpenExternal {
    return fmt.Errorf("specify only one of Open or OpenExternal")
}
// safe to call wshclient.PathCommand(ctx, data)

Try / catch

resp, err := wshclient.PathCommand(ctx, data)
if err != nil && strings.Contains(err.Error(), "open and openExternal cannot both be true") {
    data.OpenExternal = false
    resp, err = wshclient.PathCommand(ctx, data)
}

Prevention

When it happens

Trigger: Calling the wsh `path` RPC (or CLI `wsh path --open --open-external <type>`) with both PathCommandData.Open and PathCommandData.OpenExternal = true. PathType may be any of "config", "data", or "log" — the check happens before path resolution matters.

Common situations: CLI/shell aliases that accumulate open flags; scripts that set both flags by default with environment toggles; UI code passing user checkboxes for both 'open in Wave' and 'open in system app' without mutual exclusion.

Understand the failure class

Background: "mutually exclusive" flag errors: what "can't supply both nx and xx", "--raw is not compatible with -i" and "cannot be used with" mean, and how to fix them — this error's family across 29 libraries.

Related errors


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