GitbookIO/gitbook · error · Error

Iframe must have a content window

Error message

Iframe must have a content window

What it means

Thrown by createGitBookFrame in @gitbook/embed when the passed HTMLIFrameElement has no contentWindow. An iframe only gets its content window once it has been inserted into the document and its browsing context has been created, so calling this before mounting (or on a detached element) always fails. The client needs the window to set up postMessage communication with the embedded GitBook frame.

Source

Thrown at packages/embed/src/client/createGitBookFrame.ts:51

    clearChat: () => void;

    /**
     * Set the placeholder settings.
     */
    configure: (settings: Partial<GitBookEmbeddableConfiguration>) => void;

    /**
     * Register an event listener.
     */
    on: (event: string, listener: (...args: any[]) => void) => () => void;
};

/**
 * Create a client to communicate with the GitBook Assistant frame.
 */
export function createGitBookFrame(iframe: HTMLIFrameElement): GitBookFrameClient {
    if (!iframe.contentWindow) {
        throw new Error('Iframe must have a content window');
    }

    const allowTokens = iframe.allow
        .split(';')
        .map((token) => token.trim())
        .filter(Boolean);

    if (!allowTokens.includes('clipboard-write')) {
        iframe.allow = [...allowTokens, 'clipboard-write'].join('; ');
    }

    const channel = createChannel(iframe.contentWindow);

    channel.receive((message: FrameToParentMessage) => {
        console.log('[gitbook:embed] received message', message);
        if (message.type === 'close') {
            const listeners = events.get('close') || [];
            if (listeners) {

View on GitHub (pinned to db67585ee2)

Solutions

  1. Call createGitBookFrame inside useEffect (or after the iframe's load event) so the element is mounted and contentWindow exists
  2. If using a manual iframe, append it to the document before creating the frame client
  3. Guard with a check: only create the client when iframe.contentWindow is truthy

Example fix

// before
const client = createGitBookFrame(ref.current); // during render / unmounted

// after
useEffect(() => {
    if (!ref.current?.contentWindow) return;
    const client = createGitBookFrame(ref.current);
}, []);
Defensive patterns

Strategy: type-guard

Type guard

function hasContentWindow(iframe: HTMLIFrameElement | null): iframe is HTMLIFrameElement & { contentWindow: Window } {
    return !!iframe?.contentWindow;
}

Prevention

When it happens

Trigger: Calling createGitBookFrame(iframe) inside useEffect before the iframe is appended to the DOM; using a ref whose current is null or whose element was created with document.createElement but never attached; calling it during render instead of in an effect after mount.

Common situations: React integration where createGitBookFrame is called too early (during render or in a ref callback that fires before insertion); testing with jsdom where contentWindow can be null; manually constructing the iframe and forgetting document.body.appendChild; the iframe was removed from the DOM before the call.

Related errors


AI-assisted analysis of GitbookIO/gitbook@db67585ee2 (2026-08-28). Data as JSON: /api/errors/41fc5cd1e6eb23f8. Report an issue: GitHub.