wavetermdev/waveterm · error

error updating window: %w

Error message

error updating window: %w

What it means

SwitchWorkspace failed to persist the updated Window record (with its new WorkspaceId) via wstore.DBUpdate after re-pointing the window at the target workspace. This error wraps the underlying wstore/db failure, so the root cause is in the wrapped message. The window's in-memory WorkspaceId was already mutated, but the change was never committed.

Source

Thrown at pkg/wcore/window.go:52

	}

	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)
			client := wshclient.GetBareRpcClient()
			err = wshclient.FocusWindowCommand(client, w.OID, &wshrpc.RpcOpts{Route: wshutil.ElectronRoute})
			return nil, err
		}
	}
	window.WorkspaceId = workspaceId
	err = wstore.DBUpdate(ctx, window)
	if err != nil {
		return nil, fmt.Errorf("error updating window: %w", err)
	}

	deleted, _, err := DeleteWorkspace(ctx, curWsId, false)
	if err != nil && deleted {
		print(err.Error()) // @jalileh isolated the error for now, curwId/workspace was deleted when this occurs.
	} else if err != nil {
		return nil, fmt.Errorf("error deleting workspace: %w", err)
	}

	if !deleted {
		log.Printf("current workspace %s was not deleted\n", curWsId)
	} else {
		log.Printf("deleted current workspace %s\n", curWsId)
	}

	log.Printf("switching window %s to workspace %s\n", windowId, workspaceId)
	return ws, nil
}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Inspect the wrapped %w error to find the root wstore/db cause (e.g. 'not found' vs I/O error)
  2. Verify the windowId still exists with wcore.GetWindow before switching
  3. Check the DB file (~/.waveterm) for corruption or permission problems
  4. Retry the switch after confirming no concurrent modification of the same window

Example fix

// before
err = wstore.DBUpdate(ctx, window)
if err != nil {
	return nil, fmt.Errorf("error updating window: %w", err)
}
// after
window, err = GetWindow(ctx, windowId) // re-read to confirm it still exists
if err != nil {
	return nil, fmt.Errorf("window vanished before update: %w", err)
}
window.WorkspaceId = workspaceId
if err := wstore.DBUpdate(ctx, window); err != nil {
	return nil, fmt.Errorf("error updating window: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

win, err := wcore.GetWindow(ctx, windowId)
if err != nil {
	return fmt.Errorf("window %s unavailable before switch: %w", windowId, err)
}
if _, err := wcore.GetWorkspace(ctx, workspaceId); err != nil {
	return fmt.Errorf("target workspace unavailable: %w", err)
}

Type guard

func windowValid(w *waveobj.Window) bool { return w != nil && w.OID != "" && w.WorkspaceId != "" }

Try / catch

newWs, err := wcore.SwitchWorkspace(ctx, windowId, workspaceId)
if err != nil {
	if strings.Contains(err.Error(), "error updating window") {
		log.Printf("DB update failed during switch, retry after checking window state: %v", err)
		// re-fetch window and retry or abort
	}
	return err
}

Prevention

When it happens

Trigger: Calling wcore.SwitchWorkspace(ctx, windowId, workspaceId) when the target workspace exists and is not already bound to another window, and the subsequent wstore.DBUpdate(ctx, window) fails (DB closed, corrupted, OID not found, or write-level error).

Common situations: Corrupted or locked waveterm DB file; stale window OID after another process deleted the window; disk-full or permission errors on the user's state directory; racing two SwitchWorkspace calls from different clients for the same window.

Related errors


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