{"record":{"id":"723c2aafdd3f0ad4","repo":"wavetermdev/waveterm","slug":"error-getting-new-workspace-w","errorCode":null,"errorMessage":"error getting new workspace: %w","messagePattern":"error getting new workspace: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wcore/window.go","lineNumber":25,"sourceCode":"\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\n\t\"github.com/google/uuid\"\n\t\"github.com/wavetermdev/waveterm/pkg/eventbus\"\n\t\"github.com/wavetermdev/waveterm/pkg/util/utilfn\"\n\t\"github.com/wavetermdev/waveterm/pkg/waveobj\"\n\t\"github.com/wavetermdev/waveterm/pkg/wshrpc\"\n\t\"github.com/wavetermdev/waveterm/pkg/wshrpc/wshclient\"\n\t\"github.com/wavetermdev/waveterm/pkg/wshutil\"\n\t\"github.com/wavetermdev/waveterm/pkg/wstore\"\n)\n\nfunc SwitchWorkspace(ctx context.Context, windowId string, workspaceId string) (*waveobj.Workspace, error) {\n\tlog.Printf(\"SwitchWorkspace %s %s\\n\", windowId, workspaceId)\n\tws, err := GetWorkspace(ctx, workspaceId)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting new workspace: %w\", err)\n\t}\n\twindow, err := GetWindow(ctx, windowId)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting window: %w\", err)\n\t}\n\tcurWsId := window.WorkspaceId\n\tif curWsId == workspaceId {\n\t\treturn nil, nil\n\t}\n\n\tallWindows, err := wstore.DBGetAllObjsByType[*waveobj.Window](ctx, waveobj.OType_Window)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting all windows: %w\", err)\n\t}\n\n\tfor _, w := range allWindows {\n\t\tif w.WorkspaceId == workspaceId {\n\t\t\tlog.Printf(\"workspace %s already has a window %s, focusing that window\\n\", workspaceId, w.OID)","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wcore/window.go#L7-L43","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Refresh the workspace list (wstore DBGetObjsByType Workspace) and call SwitchWorkspace with a currently-existing workspaceId","Validate the workspaceId is a non-empty valid UUID and exists before calling","Handle the not-found case in the caller: fall back to the window's current workspace or the default workspace","Check the wrapped cause: if it is a DB error (not not-found), investigate the database rather than the ID"],"exampleFix":"// before\nws, _ := wclient.SwitchWorkspace(ctx, winId, staleWsId)\n// after\nwsList, _ := wcore.ListWorkspaces(ctx)\nif !containsWorkspace(wsList, wsId) {\n    wsId = wsList[0].OID // fall back to first existing workspace\n}\nws, err := wclient.SwitchWorkspace(ctx, winId, wsId)","handlingStrategy":"validation","validationCode":"_, err := wcore.GetWorkspace(ctx, workspaceId)\nif err != nil {\n    // resolve a fresh workspace list before switching\n    return fmt.Errorf(\"workspace %s unavailable: %w\", workspaceId, err)\n}","typeGuard":"func workspaceExists(ctx context.Context, id string) bool {\n    _, err := wcore.GetWorkspace(ctx, id)\n    return err == nil\n}","tryCatchPattern":"ws, err := wcore.SwitchWorkspace(ctx, winId, wsId)\nif err != nil {\n    if strings.Contains(err.Error(), \"getting new workspace\") {\n        wsList, _ := wcore.ListWorkspaces(ctx)\n        if len(wsList) > 0 { ws, err = wcore.SwitchWorkspace(ctx, winId, wsList[0].OID) }\n    }\n}","preventionTips":["Re-fetch the workspace list instead of trusting cached IDs","Treat workspace deletion events as invalidating stored selections","Validate workspaceId is a non-empty UUID before calling","Fall back to the default workspace on not-found"],"tags":["workspace","not-found","wcore","stale-reference"],"backgroundTag":"workspace-not-found","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}