wavetermdev/waveterm · error
Block not found in tab: ${blockId}
Error message
Block not found in tab: ${blockId} What it means
handle_setblockfocus located the tab's LayoutModel but getNodeByBlockId(blockId) returned null, so the block with that id is not present in this tab. The focus operation only applies to blocks within the receiving tab's layout tree.
Source
Thrown at frontend/app/store/tabrpcclient.ts:103
if (data.text) {
model.appendText(data.text);
}
if (data.submit) {
await model.handleSubmit();
}
}
async handle_setblockfocus(rh: RpcResponseHelper, blockId: string): Promise<void> {
const layoutModel = getLayoutModelForStaticTab();
if (!layoutModel) {
throw new Error("Layout model not found");
}
const node = layoutModel.getNodeByBlockId(blockId);
if (!node) {
throw new Error(`Block not found in tab: ${blockId}`);
}
layoutModel.focusNode(node.id);
}
async handle_getfocusedblockdata(rh: RpcResponseHelper): Promise<FocusedBlockData> {
const layoutModel = getLayoutModelForStaticTab();
if (!layoutModel) {
throw new Error("Layout model not found");
}
const focusedNode = globalStore.get(layoutModel.focusedNode);
const blockId = focusedNode?.data?.blockId;
if (!blockId) {
return null;
}
View on GitHub (pinned to a4447c1563)
Solutions
- Confirm the block exists in the target tab before focusing (query node map or focused block data)
- Route the RPC through the owning tab's TabRpcClient
- Purge or re-map blockIds on tab/workspace restore events
- Guard UI code that auto-focuses blocks on close/delete events
Example fix
// before
await rpcService.call("setblockfocus", [blockId]);
// after
const node = layoutModel?.getNodeByBlockId(blockId);
if (node) {
await rpcService.call("setblockfocus", [blockId]);
} else {
console.warn("skip focus, block gone:", blockId);
} Defensive patterns
Strategy: validation
Validate before calling
if (getLayoutModelForStaticTab()?.getNodeByBlockId(blockId) == null) {
console.warn("block not focusable in this tab:", blockId);
return;
} Type guard
function isFocusableBlock(blockId: string): boolean {
return getLayoutModelForStaticTab()?.getNodeByBlockId(blockId) != null;
} Try / catch
try {
await rpcService.call("setblockfocus", [blockId]);
} catch (e) {
if (String(e).startsWith("Block not found in tab:")) {
focusFirstAvailableBlock();
} else {
throw e;
}
} Prevention
- Re-map persisted blockIds after workspace/tab restore
- Send focus commands only to the tab owning the block
- Clean up focus requests when blocks are closed
When it happens
Trigger: Focusing a blockId that was closed, belongs to a different tab, or never existed in the receiving tab; stale blockId from persisted state after workspace restore.
Common situations: Multi-tab UIs sending focus commands via the wrong tab's client; hot-reload/dev scenarios where ids regenerated; automation replaying old block ids after user closed blocks.
Related errors
- Block not found: ${blockId}
- Layout model not found
- rpc command "${msg.command}" not supported by [${this.routeI
- Invalid node
- Invalid direction: ${direction}
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/59dd212060ac68f1.
Report an issue: GitHub.