wavetermdev/waveterm · error

error finding tab

Error message

error finding tab: %v

What it means

When resolving the 'tab' simple id, resolveThis finds the tab that contains the request's block via wstore.DBFindTabForBlockId. This error wraps a failure of that lookup — the tab containing the given blockId could not be found or the store lookup errored. It indicates an inconsistent block reference or store access problem.

Solutions

  1. Verify the blockId still exists (BlockInfoCommand or store lookup) before resolving 'tab'.
  2. Refresh workspace/tab state on the client and retry with a current blockId.
  3. Handle NotFound distinctly and fall back to resolving via the workspace's tab list.

Example fix

// before
oref, err := wshclient.ResolveIdsCommand(ctx, wshrpc.CommandResolveIdsData{SimpleId: "tab", BlockId: staleBlockId}, nil)
// after
if _, err := wshclient.BlockInfoCommand(ctx, staleBlockId, nil); err != nil {
    staleBlockId = currentBlockId // refresh from view state
}
oref, err := wshclient.ResolveIdsCommand(ctx, wshrpc.CommandResolveIdsData{SimpleId: "tab", BlockId: staleBlockId}, nil)
Defensive patterns

Strategy: validation

Validate before calling

_, err := wshclient.BlockInfoCommand(ctx, blockId, nil)
if err != nil {
    return fmt.Errorf("block %s gone, cannot resolve 'tab': %w", blockId, err)
}

Type guard

func isNotFound(err error) bool {
    return err != nil && (errors.Is(err, wstore.ErrNotFound) || strings.Contains(err.Error(), "not found"))
}

Try / catch

tabRef, err := wshclient.ResolveIdsCommand(ctx, wshrpc.CommandResolveIdsData{SimpleId: "tab", BlockId: blockId}, nil)
if err != nil && isNotFound(err) {
    tabRef = resolveTabFromCurrentWorkspace(blockId) // fallback path
}

Prevention

When it happens

Trigger: Calling ResolveIds with simpleId 'tab' where data.BlockId refers to a block that no longer exists, was deleted concurrently, or the wstore lookup returns an error (record missing / DB failure).

Common situations: Stale frontend state after a block was closed; resolving ids for blocks in a tab that was just removed; race between block deletion and id resolution; corrupted or out-of-sync local store.

Related errors


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

Appendix: source

Thrown at pkg/wshrpc/wshserver/resolvers.go:93

		return "uuid8", simpleId, nil
	}

	return "", "", fmt.Errorf("invalid simple id format: %s", simpleId)
}

// Individual resolvers
func resolveThis(ctx context.Context, data wshrpc.CommandResolveIdsData, value string) (*waveobj.ORef, error) {
	if data.BlockId == "" {
		return nil, fmt.Errorf("no blockid in request")
	}

	if value == SimpleId_This || value == SimpleId_Block {
		return &waveobj.ORef{OType: waveobj.OType_Block, OID: data.BlockId}, nil
	}
	if value == SimpleId_Tab {
		tabId, err := wstore.DBFindTabForBlockId(ctx, data.BlockId)
		if err != nil {
			return nil, fmt.Errorf("error finding tab: %v", err)
		}
		return &waveobj.ORef{OType: waveobj.OType_Tab, OID: tabId}, nil
	}
	if value == SimpleId_Ws || value == SimpleId_Workspace {
		tabId, err := wstore.DBFindTabForBlockId(ctx, data.BlockId)
		if err != nil {
			return nil, fmt.Errorf("error finding tab: %v", err)
		}
		wsId, err := wstore.DBFindWorkspaceForTabId(ctx, tabId)
		if err != nil {
			return nil, fmt.Errorf("error finding workspace: %v", err)
		}
		return &waveobj.ORef{OType: waveobj.OType_Workspace, OID: wsId}, nil
	}
	if value == SimpleId_Client || value == SimpleId_Global {
		clientId := wstore.GetClientId()
		return &waveobj.ORef{OType: waveobj.OType_Client, OID: clientId}, nil
	}

View on GitHub (pinned to a4447c1563)