wavetermdev/waveterm · error
Display container not found
Error message
Display container not found
What it means
captureBlockScreenshot found the layout node for the block, but the LayoutModel's displayContainerRef.current is null — the DOM element that hosts all blocks is not mounted. The container's bounding rect is required to compute absolute coordinates for Electron's capturePage, so the operation cannot proceed.
Source
Thrown at frontend/app/store/tabrpcclient.ts:35
handle_captureblockscreenshot(rh: RpcResponseHelper, data: CommandCaptureBlockScreenshotData): Promise<string> {
return this.captureBlockScreenshot(data.blockid);
}
async captureBlockScreenshot(blockId: string): Promise<string> {
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: ${blockId}`);
}
const displayContainer = layoutModel.displayContainerRef.current;
if (!displayContainer) {
throw new Error("Display container not found");
}
const containerRect = displayContainer.getBoundingClientRect();
const additionalProps = layoutModel.getNodeAdditionalProperties(node);
let electronRect: Electron.Rectangle;
if (!additionalProps?.rect) {
// Bug: rect is not set when there is only one block in the layout
// In this case, use the full container rect
electronRect = {
x: Math.round(containerRect.x),
y: Math.round(containerRect.y),
width: Math.round(containerRect.width),
height: Math.round(containerRect.height),
};
} else {
const blockRect = additionalProps.rect;View on GitHub (pinned to a4447c1563)
Solutions
- Wait until the tab is fully rendered before capturing (e.g. await a mounted flag or requestAnimationFrame)
- Retry the RPC after a short delay if it races mount/unmount
- Cancel queued screenshot requests when the tab/window closes
- Verify the block is in the visible tab, not a background tab whose container is unmounted
Example fix
// before
const containerRect = displayContainer.getBoundingClientRect();
// after
if (!displayContainer) {
await new Promise((r) => requestAnimationFrame(r));
displayContainer = layoutModel.displayContainerRef.current;
if (!displayContainer) throw new Error("Display container not found");
}
const containerRect = displayContainer.getBoundingClientRect(); Defensive patterns
Strategy: retry
Validate before calling
const displayContainer = getLayoutModelForStaticTab()?.displayContainerRef.current;
if (!displayContainer) {
throw new Error("display container not mounted; cannot capture");
} Type guard
function displayContainerMounted(): boolean {
return getLayoutModelForStaticTab()?.displayContainerRef.current != null;
} Try / catch
try {
const pngData = await rpcService.call("captureblockscreenshot", { blockid });
} catch (e) {
if (String(e).includes("Display container not found")) {
await nextFrame();
pngData = await rpcService.call("captureblockscreenshot", { blockid });
} else {
throw e;
}
} Prevention
- Defer captures until after mount (requestAnimationFrame or mounted callback)
- Skip captures for background tabs whose containers are unmounted
- Guard ref consumers against null .current before layout commit
When it happens
Trigger: The RPC runs while the tab's display container is unmounted — during tab close, window minimize with unmounted DOM, or before the layout component's ref has attached (very early after mount).
Common situations: Automated screenshot right after window/tab creation racing React's commit; capturing during workspace/tab teardown; tests or headless environments where the display container never renders.
Related errors
- Layout model not found
- Block not found: ${blockId}
- failed to capture screenshot: %w
- no job attached to controller
- error getting block: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/470508cc381fac23.
Report an issue: GitHub.