garrytan/gstack · warning · Error

Cannot use reload inside a frame. Run 'frame main' first.

Error message

Cannot use reload inside a frame. Run 'frame main' first.

What it means

Frame-context guard in the reload case at write-commands.ts:173. page.reload() targets the top-level page and is refused when a subframe context is active (session.getFrame() !== null).

Source

Thrown at browse/src/write-commands.ts:172

      return `Navigated to ${normalizedUrl} (${status})`;
    }

    case 'back': {
      if (inFrame) throw new Error('Cannot use back inside a frame. Run \'frame main\' first.');
      session.clearLoadedHtml();
      await page.goBack({ waitUntil: 'domcontentloaded', timeout: 15000 });
      return `Back → ${page.url()}`;
    }

    case 'forward': {
      if (inFrame) throw new Error('Cannot use forward inside a frame. Run \'frame main\' first.');
      session.clearLoadedHtml();
      await page.goForward({ waitUntil: 'domcontentloaded', timeout: 15000 });
      return `Forward → ${page.url()}`;
    }

    case 'reload': {
      if (inFrame) throw new Error('Cannot use reload inside a frame. Run \'frame main\' first.');
      session.clearLoadedHtml();
      await page.reload({ waitUntil: 'domcontentloaded', timeout: 15000 });
      return `Reloaded ${page.url()}`;
    }

    case 'load-html': {
      if (inFrame) throw new Error('Cannot use load-html inside a frame. Run \'frame main\' first.');

      // --from-file <path.json>: read inline HTML from a JSON payload. Used by
      // make-pdf to dodge Windows argv size limits on large rendered HTML.
      // The JSON shape is { html: string, waitUntil?: "load"|"domcontentloaded"|"networkidle" }.
      // The safe-dirs + magic-byte + size-cap checks below still apply to the
      // INLINE HTML content, not to the payload file path itself.
      let fromFilePayload: { html: string; waitUntil?: SetContentWaitUntil } | null = null;
      let filePath: string | undefined;
      let waitUntil: SetContentWaitUntil = 'domcontentloaded';
      for (let i = 0; i < args.length; i++) {
        if (args[i] === '--from-file') {

View on GitHub (pinned to 94993f7401)

Solutions

  1. Run 'frame main' before 'reload'
  2. Issue reload before entering any frame in the flow
  3. Guard on session.getFrame() === null

Example fix

// before
await handleWriteCommand('reload', [], session, bm)  // in frame → throws
// after
await handleWriteCommand('frame', ['main'], session, bm)
await handleWriteCommand('reload', [], session, bm)
Defensive patterns

Strategy: validation

Validate before calling

function canNavigate(session: { getFrame(): unknown }): boolean {
  return session.getFrame() === null
}

Type guard

function isMainFrameSession(s: { getFrame(): unknown }): boolean {
  return s.getFrame() === null
}

Prevention

When it happens

Trigger: Running 'reload' while a frame context is active.

Common situations: Refreshing the page after interacting inside an iframe, forgetting the frame context is still set.

Related errors


AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12). Data as JSON: /api/errors/1c8dd054c9f1896f. Report an issue: GitHub.