wavetermdev/waveterm · error

error getting tab: %w

Error message

error getting tab: %w

What it means

GetTab wraps any failure from wstore.DBGet[*waveobj.Tab] with 'error getting tab: %w'. It is thrown when the tab lookup in the wstore database fails — most often because no Tab object exists for the given tabId, or the underlying DB read errored. The wrapped error is preserved so callers can inspect the root cause (e.g. 'key not found').

Source

Thrown at pkg/service/clientservice/clientservice.go:37

)

type ClientService struct{}

const DefaultTimeout = 2 * time.Second

func (cs *ClientService) GetClientData() (*waveobj.Client, error) {
	log.Println("GetClientData")
	ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
	defer cancelFn()
	return wcore.GetClientData(ctx)
}

func (cs *ClientService) GetTab(tabId string) (*waveobj.Tab, error) {
	ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
	defer cancelFn()
	tab, err := wstore.DBGet[*waveobj.Tab](ctx, tabId)
	if err != nil {
		return nil, fmt.Errorf("error getting tab: %w", err)
	}
	return tab, nil
}

func (cs *ClientService) GetAllConnStatus(ctx context.Context) ([]wshrpc.ConnStatus, error) {
	sshStatuses := conncontroller.GetAllConnStatus()
	wslStatuses := wslconn.GetAllConnStatus()
	return append(sshStatuses, wslStatuses...), nil
}

// moves the window to the front of the windowId stack
func (cs *ClientService) FocusWindow(ctx context.Context, windowId string) error {
	return wcore.FocusWindow(ctx, windowId)
}

func (cs *ClientService) AgreeTos(ctx context.Context) (waveobj.UpdatesRtnType, error) {
	ctx = waveobj.ContextWithUpdates(ctx)
	clientData, err := wstore.DBGetSingleton[*waveobj.Client](ctx)

View on GitHub (pinned to a4447c1563)

Solutions

  1. Verify the tabId exists (check it came from a current window/tab list, not a stale cache)
  2. Check the wrapped error: if 'key not found', treat the tab as deleted and refresh the tab list
  3. If DB errors persist, inspect the wstore DB file for corruption/permissions

Example fix

// before
tab, err := cs.GetTab(staleTabId)
// after
tab, err := cs.GetTab(tabId)
if err != nil && strings.Contains(err.Error(), "key not found") {
    tab, err = cs.GetTab(currentTabId) // re-resolve from active window
}
Defensive patterns

Strategy: try-catch

Validate before calling

if tabId == "" { return fmt.Errorf("tabId required") }

Type guard

func hasTabId(tabId string) bool { return strings.TrimSpace(tabId) != "" }

Try / catch

tab, err := cs.GetTab(tabId)
if err != nil {
    if strings.Contains(err.Error(), "key not found") { /* tab deleted; refresh list */ }
    return err
}

Prevention

When it happens

Trigger: Calling ClientService.GetTab with a tabId that was deleted, a typo'd/stale tabId from a cached reference, or when the wstore DB read fails (IO/corruption).

Common situations: Frontend holds a tabId after the tab was closed in another window; restoring workspace state referencing removed tabs; passing a blockId or windowId instead of a tabId.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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