wavetermdev/waveterm · error

error getting new workspace: %w

Error message

error getting new workspace: %w

What it means

SwitchWorkspace first loads the target workspace with GetWorkspace before switching the window to it. This error wraps any failure of that lookup — the workspace ID does not resolve to an existing Workspace object, or the DB read failed. The window is left unchanged.

Source

Thrown at pkg/wcore/window.go:25

	"context"
	"fmt"
	"log"

	"github.com/google/uuid"
	"github.com/wavetermdev/waveterm/pkg/eventbus"
	"github.com/wavetermdev/waveterm/pkg/util/utilfn"
	"github.com/wavetermdev/waveterm/pkg/waveobj"
	"github.com/wavetermdev/waveterm/pkg/wshrpc"
	"github.com/wavetermdev/waveterm/pkg/wshrpc/wshclient"
	"github.com/wavetermdev/waveterm/pkg/wshutil"
	"github.com/wavetermdev/waveterm/pkg/wstore"
)

func SwitchWorkspace(ctx context.Context, windowId string, workspaceId string) (*waveobj.Workspace, error) {
	log.Printf("SwitchWorkspace %s %s\n", windowId, workspaceId)
	ws, err := GetWorkspace(ctx, workspaceId)
	if err != nil {
		return nil, fmt.Errorf("error getting new workspace: %w", err)
	}
	window, err := GetWindow(ctx, windowId)
	if err != nil {
		return nil, fmt.Errorf("error getting window: %w", err)
	}
	curWsId := window.WorkspaceId
	if curWsId == workspaceId {
		return nil, nil
	}

	allWindows, err := wstore.DBGetAllObjsByType[*waveobj.Window](ctx, waveobj.OType_Window)
	if err != nil {
		return nil, fmt.Errorf("error getting all windows: %w", err)
	}

	for _, w := range allWindows {
		if w.WorkspaceId == workspaceId {
			log.Printf("workspace %s already has a window %s, focusing that window\n", workspaceId, w.OID)

View on GitHub (pinned to a4447c1563)

Solutions

  1. Refresh the workspace list (wstore DBGetObjsByType Workspace) and call SwitchWorkspace with a currently-existing workspaceId
  2. Validate the workspaceId is a non-empty valid UUID and exists before calling
  3. Handle the not-found case in the caller: fall back to the window's current workspace or the default workspace
  4. Check the wrapped cause: if it is a DB error (not not-found), investigate the database rather than the ID

Example fix

// before
ws, _ := wclient.SwitchWorkspace(ctx, winId, staleWsId)
// after
wsList, _ := wcore.ListWorkspaces(ctx)
if !containsWorkspace(wsList, wsId) {
    wsId = wsList[0].OID // fall back to first existing workspace
}
ws, err := wclient.SwitchWorkspace(ctx, winId, wsId)
Defensive patterns

Strategy: validation

Validate before calling

_, err := wcore.GetWorkspace(ctx, workspaceId)
if err != nil {
    // resolve a fresh workspace list before switching
    return fmt.Errorf("workspace %s unavailable: %w", workspaceId, err)
}

Type guard

func workspaceExists(ctx context.Context, id string) bool {
    _, err := wcore.GetWorkspace(ctx, id)
    return err == nil
}

Try / catch

ws, err := wcore.SwitchWorkspace(ctx, winId, wsId)
if err != nil {
    if strings.Contains(err.Error(), "getting new workspace") {
        wsList, _ := wcore.ListWorkspaces(ctx)
        if len(wsList) > 0 { ws, err = wcore.SwitchWorkspace(ctx, winId, wsList[0].OID) }
    }
}

Prevention

When it happens

Trigger: Calling SwitchWorkspace(ctx, windowId, workspaceId) with a workspaceId that is not a valid/existing workspace OID (returns not-found through GetWorkspace), a stale/deleted workspace ID from the frontend, or a DB read error.

Common situations: Frontend holds a cached workspace list and the workspace was deleted in another window/process; malformed workspaceId passed over RPC; stale bookmarks or startup-restore referencing a removed workspace.

Related errors


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