wavetermdev/waveterm · error
error setting active tab: %w
Error message
error setting active tab: %w
What it means
SetActiveTab changes the workspace's active tab and returns update events. If wcore.SetActiveTab fails (workspace or tab not found, DB error, timeout), the error is wrapped as "error setting active tab: %w". It indicates the tab switch could not be persisted before any controllers are started.
Source
Thrown at pkg/service/workspaceservice/workspaceservice.go:179
}()
wps.Broker.SendUpdateEvents(updates)
}()
return tabId, updates, nil
}
func (svc *WorkspaceService) SetActiveTab_Meta() tsgenmeta.MethodMeta {
return tsgenmeta.MethodMeta{
ArgNames: []string{"workspaceId", "tabId"},
}
}
func (svc *WorkspaceService) SetActiveTab(workspaceId string, tabId string) (waveobj.UpdatesRtnType, error) {
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancelFn()
ctx = waveobj.ContextWithUpdates(ctx)
err := wcore.SetActiveTab(ctx, workspaceId, tabId)
if err != nil {
return nil, fmt.Errorf("error setting active tab: %w", err)
}
// check all blocks in tab and start controllers (if necessary)
tab, err := wstore.DBMustGet[*waveobj.Tab](ctx, tabId)
if err != nil {
return nil, fmt.Errorf("error getting tab: %w", err)
}
blockORefs := tab.GetBlockORefs()
blocks, err := wstore.DBSelectORefs(ctx, blockORefs)
if err != nil {
return nil, fmt.Errorf("error getting tab blocks: %w", err)
}
updates := waveobj.ContextGetUpdatesRtn(ctx)
go func() {
defer func() {
panichandler.PanicHandler("WorkspaceService:SetActiveTab:SendUpdateEvents", recover())
}()
wps.Broker.SendUpdateEvents(updates)
}()View on GitHub (pinned to a4447c1563)
Solutions
- Verify the tabId exists in the workspace before calling SetActiveTab
- Unwrap the error to see whether wcore.SetActiveTab reported a not-found vs DB failure
- Refresh the client's view of the workspace to clear stale tab ids
- Check DB health and DefaultTimeout headroom
Example fix
// before
wsSvc.SetActiveTab(workspaceId, possiblyStaleTabId)
// after
tab, err := wstore.DBGet[*waveobj.Tab](ctx, possiblyStaleTabId)
if err != nil { return fmt.Errorf("tab no longer exists: %w", err) }
wsSvc.SetActiveTab(workspaceId, tab.OID) Defensive patterns
Strategy: validation
Validate before calling
ws, err := wstore.DBGet[*waveobj.Workspace](ctx, workspaceId)
if err != nil { return err }
if !slices.Contains(ws.TabIds, tabId) {
return fmt.Errorf("tab %s not in workspace %s", tabId, workspaceId)
}
_, err = svc.SetActiveTab(workspaceId, tabId) Try / catch
_, err := svc.SetActiveTab(workspaceId, tabId)
if err != nil {
if errors.Is(err, waveobj.ErrNotFound) { /* reload workspace state */ }
return err
} Prevention
- Confirm tabId belongs to the target workspace before activation
- Handle tab-deleted events promptly in the UI
- Avoid calling SetActiveTab concurrently with CloseTab on the same tab
When it happens
Trigger: Calling SetActiveTab(workspaceId, tabId) with a tabId that does not belong to the given workspace, a nonexistent workspaceId, or a DB/timeout failure inside wcore.SetActiveTab.
Common situations: Frontend holding a stale tabId after the tab was closed elsewhere; race between closing a tab and switching to it; corrupted workspace state.
Related errors
- error creating tab: %w
- error getting tab: %w
- error closing tab: %w
- nil wshrpc passed to wshclient
- no default route
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/6ab7c00e7f577889.
Report an issue: GitHub.