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

  1. Wait until the tab is fully rendered before capturing (e.g. await a mounted flag or requestAnimationFrame)
  2. Retry the RPC after a short delay if it races mount/unmount
  3. Cancel queued screenshot requests when the tab/window closes
  4. 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

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


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