wavetermdev/waveterm · error

error getting tab blocks: %w

Error message

error getting tab blocks: %w

What it means

After fetching the tab, SetActiveTab loads all of the tab's block objects via wstore.DBSelectORefs to decide which shell controllers to start. If loading any block reference fails, the error is wrapped as "error getting tab blocks: %w". This means the tab exists but one or more of its child block records cannot be read.

Source

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

}

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
}

type CloseTabRtnType struct {
	CloseWindow    bool   `json:"closewindow,omitempty"`
	NewActiveTabId string `json:"newactivetabid,omitempty"`

View on GitHub (pinned to a4447c1563)

Solutions

  1. Inspect the tab's blockrefs and remove dangling ORefs pointing at missing blocks
  2. Unwrap the error to identify the specific failing block oref
  3. Restore the wave DB from backup if corruption is widespread
  4. Avoid killing the app mid-write to prevent orphaned blockrefs

Example fix

// before
blocks, err := wstore.DBSelectORefs(ctx, blockORefs) // some orefs dangling
// after
var valid []waveobj.ORef
for _, oref := range blockORefs {
    if _, err := wstore.DBGet(ctx, oref.OType, oref.OID); err == nil {
        valid = append(valid, oref)
    }
}
blocks, err := wstore.DBSelectORefs(ctx, valid)
Defensive patterns

Strategy: validation

Validate before calling

tab, err := wstore.DBGet[*waveobj.Tab](ctx, tabId)
if err != nil { return err }
for _, oref := range tab.GetBlockORefs() {
    if _, err := wstore.DBGet(ctx, oref.OType, oref.OID); err != nil {
        return fmt.Errorf("dangling block ref %s: %w", oref, err)
    }
}

Try / catch

_, err := svc.SetActiveTab(workspaceId, tabId)
if err != nil {
    var dbErr *wstore.ErrDB
    if errors.As(errors.Unwrap(err), &dbErr) { /* repair blockrefs */ }
    return err
}

Prevention

When it happens

Trigger: A tab whose blockrefs point to blocks that are missing from the DB, or a storage failure during DBSelectORefs, triggered by SetActiveTab on such a tab.

Common situations: Partially deleted or corrupted tab state (block rows removed without updating tab.blockrefs), interrupted writes from a crash.

Related errors


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