wavetermdev/waveterm · error
error finding tab: %v
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.
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)
Solutions
- Verify the blockId still exists (BlockInfoCommand or store lookup) before resolving 'tab'.
- Refresh workspace/tab state on the client and retry with a current blockId.
- 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
- Refresh local block references after tab/block deletions
- Subscribe to workspace change events to drop stale block ids
- Resolve 'tab' only for live, currently mounted blocks
- Handle NotFound distinctly from generic errors
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
- error getting block: %w
- error finding tab for block: %w
- object reference is not a block
- delete block failed: %v
- opening config file: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/5974e15d391bdb32.
Report an issue: GitHub.