wavetermdev/waveterm · error
error getting workspace: %w
Error message
error getting workspace: %w
What it means
CreateWindow with a non-empty workspaceId looks up the target workspace via GetWorkspace; this error wraps the lookup failure. GetWorkspace uses DBMustGet, so a missing OID is itself an error here, not a nil result.
Source
Thrown at pkg/wcore/window.go:93
log.Printf("error getting window %q: %v\n", windowId, err)
return nil, err
}
return window, nil
}
func CreateWindow(ctx context.Context, winSize *waveobj.WinSize, workspaceId string) (*waveobj.Window, error) {
log.Printf("CreateWindow %v %v\n", winSize, workspaceId)
var ws *waveobj.Workspace
if workspaceId == "" {
ws1, err := CreateWorkspace(ctx, "", "", "", false, false)
if err != nil {
return nil, fmt.Errorf("error creating workspace: %w", err)
}
ws = ws1
} else {
ws1, err := GetWorkspace(ctx, workspaceId)
if err != nil {
return nil, fmt.Errorf("error getting workspace: %w", err)
}
ws = ws1
}
windowId := uuid.NewString()
if winSize == nil {
winSize = &waveobj.WinSize{
Width: 0,
Height: 0,
}
}
window := &waveobj.Window{
OID: windowId,
WorkspaceId: ws.OID,
IsNew: true,
Pos: waveobj.Point{
X: 0,
Y: 0,
},View on GitHub (pinned to a4447c1563)
Solutions
- Validate the workspaceId exists before calling CreateWindow (fetch workspace list first)
- Pass "" for workspaceId to let CreateWindow make a fresh workspace instead
- Check the wrapped %w error for 'not found' vs I/O failure
- Refresh any cached workspace IDs after workspaces are deleted
Example fix
// before
win, err := wcore.CreateWindow(ctx, nil, staleWorkspaceId)
// after
wsList, err := wstore.DBGetAllObjsByType[*waveobj.Workspace](ctx, waveobj.OType_Workspace)
if err != nil {
return err
}
var wsId string
for _, ws := range wsList {
if ws.OID == staleWorkspaceId {
wsId = staleWorkspaceId
break
}
}
win, err := wcore.CreateWindow(ctx, nil, wsId) // "" if not found -> creates new workspace Defensive patterns
Strategy: validation
Validate before calling
func workspaceExists(ctx context.Context, wsId string) bool {
if wsId == "" {
return true // CreateWindow will make a new one
}
_, err := wcore.GetWorkspace(ctx, wsId)
return err == nil
} Type guard
func hasWorkspaceId(workspaceId string) bool {
_, err := uuid.Parse(workspaceId)
return err == nil
} Try / catch
win, err := wcore.CreateWindow(ctx, winSize, workspaceId)
if err != nil && strings.Contains(err.Error(), "error getting workspace") {
log.Printf("workspace %s gone, falling back to new workspace", workspaceId)
win, err = wcore.CreateWindow(ctx, winSize, "")
} Prevention
- Never cache workspaceIds across sessions without revalidating them
- Remember CloseWindow auto-deletes empty workspaces — an old ID may be stale
- Pass "" instead of a dubious ID to get a fresh workspace
When it happens
Trigger: wcore.CreateWindow(ctx, winSize, workspaceId) where workspaceId is non-empty and GetWorkspace fails — typically the workspace OID does not exist in wstore (deleted by another client) or the DB read fails.
Common situations: Caller passes a stale workspaceId saved from a previous session; workspace was deleted when its last window closed (CloseWindow auto-deletes empty workspaces); typo'd or malformed UUID; DB read error.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- error updating window: %w
- error deleting workspace: %w
- error creating workspace: %w
- no WAVETERM_TABID env var set
- create block failed: %v
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/19438233f10a9d6f.
Report an issue: GitHub.