wavetermdev/waveterm · error

error getting tab: %w

Error message

error getting tab: %w

What it means

After switching the active tab, SetActiveTab fetches the Tab object with wstore.DBMustGet[*waveobj.Tab] to enumerate its blocks. If that fetch fails, the error is wrapped as "error getting tab: %w". Notably this can occur even though SetActiveTab succeeded, meaning the tabId exists for activation but could not be read from the store.

Source

Thrown at pkg/service/workspaceservice/workspaceservice.go:184

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)
	}()
	var extraUpdates waveobj.UpdatesRtnType
	extraUpdates = append(extraUpdates, updates...)
	extraUpdates = append(extraUpdates, waveobj.MakeUpdate(tab))
	extraUpdates = append(extraUpdates, waveobj.MakeUpdates(blocks)...)
	return extraUpdates, nil

View on GitHub (pinned to a4447c1563)

Solutions

  1. Unwrap the error to distinguish not-found from I/O failure
  2. Re-fetch workspace state and retry SetActiveTab with a valid tabId
  3. Check for concurrent CloseTab/DeleteTab races against the same tabId
  4. Verify DB integrity

Example fix

// before
_, err = wsSvc.SetActiveTab(wsId, tabId) // error getting tab
// after
tab, err := wstore.DBGet[*waveobj.Tab](ctx, tabId)
if err == nil {
    _, err = wsSvc.SetActiveTab(wsId, tabId)
}
Defensive patterns

Strategy: validation

Validate before calling

if _, err := wstore.DBGet[*waveobj.Tab](ctx, tabId); err != nil {
    return fmt.Errorf("tab %s unreadable, cannot activate: %w", tabId, err)
}
_, err = svc.SetActiveTab(workspaceId, tabId)

Try / catch

rtn, err := svc.SetActiveTab(workspaceId, tabId)
if err != nil {
    if strings.Contains(err.Error(), "error getting tab") { /* DB read failure path */ }
    return err
}

Prevention

When it happens

Trigger: Calling SetActiveTab with a tabId that is set as active but missing/deleted in the DB (DBMustGet panics-free path returns error), or a storage failure reading the Tab object.

Common situations: Race condition where the tab is deleted between the SetActiveTab core call and the DBMustGet; DB corruption; stale tab id.

Related errors


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