microsoft/playwright · error · Error
No dialog visible
Error message
No dialog visible
What it means
Thrown by the browser_handle_dialog tool when tab.modalStates() contains no entry with type === 'dialog'. The tool is only valid while a JS dialog (alert/confirm/prompt/beforeunload) is currently pending on the tab.
Source
Thrown at packages/playwright-core/src/tools/backend/dialogs.ts:37
export const handleDialog = defineTabTool({
capability: 'core',
schema: {
name: 'browser_handle_dialog',
title: 'Handle a dialog',
description: 'Handle a dialog',
inputSchema: z.object({
accept: z.boolean().describe('Whether to accept the dialog.'),
promptText: z.string().optional().describe('The text of the prompt in case of a prompt dialog.'),
}),
type: 'action',
},
handle: async (tab, params, response) => {
const dialogState = tab.modalStates().find(state => state.type === 'dialog');
if (!dialogState)
throw new Error('No dialog visible');
tab.clearModalState(dialogState);
await tab.waitForCompletion(async () => {
if (params.accept)
await dialogState.dialog.accept(params.promptText);
else
await dialogState.dialog.dismiss();
});
},
clearsModalState: 'dialog',
});
export default [
handleDialog,
];
View on GitHub (pinned to c8fc3bf8d3)
Solutions
- Register a dialog listener and only invoke the tool while the dialog state is present.
- Use page.waitForEvent('dialog') (or tab.waitForCompletion) to synchronize before handling.
- Re-snapshot the tab modal states and skip the call when none of type 'dialog' exist.
Example fix
// before
await client.callTool('browser_handle_dialog', { accept: true }); // throws if no dialog
// after
page.on('dialog', async d => {
await client.callTool('browser_handle_dialog', { accept: true, promptText: d.defaultValue() });
}); Defensive patterns
Strategy: validation
Validate before calling
// Only call the tool while a dialog modal state exists.
const states = tab.modalStates();
const hasDialog = states.some(s => s.type === 'dialog');
if (hasDialog) {
await client.callTool('browser_handle_dialog', { accept: true });
} Type guard
import type { ModalState } from './tab';
function isDialogModal(s: ModalState): boolean {
return s.type === 'dialog';
} Try / catch
try {
await client.callTool('browser_handle_dialog', { accept: true });
} catch (e) {
if (e instanceof Error && e.message === 'No dialog visible') {
// not actually an error in your flow; ignore
} else throw e;
} Prevention
- Register page.on('dialog') and drive handling from the event, not speculatively.
- Treat 'No dialog visible' as benign if your flow is best-effort.
- Do not auto-retry dialog handling; re-snapshot first.
When it happens
Trigger: Calling browser_handle_dialog when no dialog event has fired, or after the dialog was already cleared (clearModalState was invoked, e.g. by a previous handle call or auto-dismiss).
Common situations: Agent proactively calling handle-dialog 'just in case'; race where the dialog was dismissed by page navigation before the tool ran; missed the page.on('dialog') listener registration.
Related errors
- No file chooser visible
- Video recording has already been started.
- Invalid location "${params.location}", expected format is <f
- At least one of "paths" or "data" must be provided.
- fullPage cannot be used with element screenshots.
AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12).
Data as JSON: /api/errors/a54b3eeb8598697f.
Report an issue: GitHub.