openclaw/openclaw · error
Dialog "${dialogId}" is not pending.
Error message
Dialog "${dialogId}" is not pending. What it means
Thrown by resolvePendingDialogForResponse (extensions/browser/src/browser/pw-session-dialogs.ts:158). The caller supplied a dialogId, but no entry in state.pendingDialogs has a matching id. The targeted dialog was already responded to, was auto-dismissed (e.g. by navigation or armed response expiry), or the id is simply wrong.
Source
Thrown at extensions/browser/src/browser/pw-session-dialogs.ts:158
return;
}
if (armed) {
clearArmedDialogResponse(pageState);
}
abortActionsBlockedByDialog(pageState);
}
export function resolvePendingDialogForResponse(params: {
state: PageState;
dialogId?: string;
}): PendingObservedDialog {
const dialogId = normalizeOptionalString(params.dialogId);
if (dialogId) {
const found = params.state.pendingDialogs.find((dialog) => dialog.id === dialogId);
if (found) {
return found;
}
throw new Error(`Dialog "${dialogId}" is not pending.`);
}
if (params.state.pendingDialogs.length === 1) {
return expectDefined(params.state.pendingDialogs.at(0), "single pending browser dialog");
}
if (params.state.pendingDialogs.length > 1) {
throw new Error("Multiple dialogs are pending; pass dialogId.");
}
throw new Error("No dialog is pending.");
}
/** Respond to a pending observed dialog on a page. */
View on GitHub (pinned to 01804a7531)
Solutions
- Re-snapshot page state and read the current pendingDialogs; respond with a live dialogId.
- If exactly one dialog is pending, omit dialogId and let the resolver pick it.
- Treat 'not pending' as a no-op success if the dialog was already handled.
Example fix
// before: stale dialogId
await respondDialog({ dialogId: oldId, accept: true });
// after: pick a live dialog
const { pendingDialogs } = await snapshot(state);
if (pendingDialogs.length === 1) {
await respondDialog({ accept: true }); // omit dialogId
} else if (pendingDialogs.length) {
await respondDialog({ dialogId: pendingDialogs[0].id, accept: true });
} Defensive patterns
Strategy: validation
Validate before calling
// Before responding, confirm the dialogId is still pending.
const { pendingDialogs } = await snapshotPageState(page);
if (dialogId && !pendingDialogs.some((d) => d.id === dialogId)) {
// dialog already gone; treat as no-op instead of erroring
return { ok: true, alreadyClosed: true };
}
await respondDialog({ dialogId, accept }); Type guard
function isPendingDialogId(state, id): boolean {
return typeof id === "string" && state.pendingDialogs.some((d) => d.id === id);
} Try / catch
try {
await respondDialog({ dialogId, accept: true });
} catch (err) {
if (err.message === `Dialog "${dialogId}" is not pending.`) {
// already handled or dismissed; safe to continue
return;
}
throw err;
} Prevention
- Re-snapshot page state before responding to capture the live pendingDialogs list.
- Omit dialogId when exactly one dialog is pending to avoid id drift.
- Treat 'not pending' as a no-op when the dialog was already handled.
When it happens
Trigger: Responding to a dialog with a dialogId captured from an older snapshot; calling respond twice for the same dialog; the page dismissed the dialog (navigation, armed response fired, or it was a transient alert) between snapshot and response; typo'd dialogId.
Common situations: Race between an armed dialog response (armedDialogResponse) auto-settling and an explicit respond call; concurrent respond attempts; snapshot taken before the dialog was promoted into pendingDialogs.
Related errors
- Multiple dialogs are pending; pass dialogId.
- No dialog is pending.
- url is required
- Invalid URL: ${diagnostic}
- output path is required
AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12).
Data as JSON: /api/errors/a1750e157763e9bd.
Report an issue: GitHub.