garrytan/gstack · warning · Error
Cannot use goto inside a frame. Run 'frame main' first.
Error message
Cannot use goto inside a frame. Run 'frame main' first.
What it means
Frame-context guard in the goto case at write-commands.ts:145. Navigation targets the top-level page, but session.getFrame() is non-null — meaning a subframe was selected via the 'frame' command. goto on a frame-scoped session is disallowed to prevent accidentally navigating only a subframe.
Source
Thrown at browse/src/write-commands.ts:145
// Follow prompts
'[class*="follow-us"]', '[class*="social-follow"]',
],
};
export async function handleWriteCommand(
command: string,
args: string[],
session: TabSession,
bm: BrowserManager
): Promise<string> {
const page = session.getPage();
// Frame-aware target for locator-based operations (click, fill, etc.)
const target = session.getActiveFrameOrPage();
const inFrame = session.getFrame() !== null;
switch (command) {
case 'goto': {
if (inFrame) throw new Error('Cannot use goto inside a frame. Run \'frame main\' first.');
const url = args[0];
if (!url) throw new Error('Usage: browse goto <url>');
// Clear loadedHtml BEFORE navigation — a timeout after the main-frame commit
// must not leave stale content that could resurrect on a later context recreation.
session.clearLoadedHtml();
const normalizedUrl = await validateNavigationUrl(url);
const response = await page.goto(normalizedUrl, { waitUntil: 'domcontentloaded', timeout: 15000 });
const status = response?.status() || 'unknown';
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()}`;
}
View on GitHub (pinned to 94993f7401)
Solutions
- Run 'frame main' to reset to the top-level page before issuing goto
- Reorder the script so all top-level navigations happen before entering any frame
- Check session.getFrame() === null in automation before calling goto
Example fix
// before (in subframe context)
await handleWriteCommand('goto', [url], session, bm) // throws
// after
await handleWriteCommand('frame', ['main'], session, bm)
await handleWriteCommand('goto', [url], session, bm) Defensive patterns
Strategy: validation
Validate before calling
function canNavigate(session: { getFrame(): unknown }): boolean {
return session.getFrame() === null
}
// Usage: if (!canNavigate(session)) await handleWriteCommand('frame', ['main'], session, bm) Type guard
function isMainFrameSession(s: { getFrame(): unknown }): boolean {
return s.getFrame() === null
} Prevention
- Always issue 'frame main' before any navigation command
- Structure scripts so all navigations precede frame entry
- Assert getFrame() === null in automation before goto
When it happens
Trigger: Running the sequence: 'frame <iframe-selector>' (or frame <id>) followed by 'goto <url>' without resetting to the main frame first.
Common situations: A script drills into an iframe to fill a field, then continues to the next navigation step without exiting the frame context.
Related errors
- Cannot use back inside a frame. Run 'frame main' first.
- Cannot use forward inside a frame. Run 'frame main' first.
- Cannot use reload inside a frame. Run 'frame main' first.
- Cannot use load-html inside a frame. Run 'frame main' first.
- Usage: browse goto <url>
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/613b4c7ca3e5b3b1.
Report an issue: GitHub.