youzan/vant-weapp · warning
未找到 van-dialog 节点,请确认 selector 及 context 是否正确
Error message
未找到 van-dialog 节点,请确认 selector 及 context 是否正确
What it means
This warning is emitted by Vant Weapp's Dialog.alert/Dialog.confirm when context.selectComponent(options.selector) fails to find a <van-dialog> component instance in the current page/component tree. The imperative Dialog API does not create the component for you — it only drives an existing <van-dialog id="van-dialog"> node declared in WXML — so when the node is missing (or the selector/context is wrong), the library can only warn; no dialog is shown and the returned Promise never resolves or rejects, silently hanging any await on it.
Source
Thrown at packages/dialog/dialog.ts:113
if (dialog) {
dialog.setData({
callback: (
action: Action,
instance: WechatMiniprogram.Component.TrivialInstance
) => {
action === 'confirm' ? resolve(instance) : reject(instance);
},
...options,
});
wx.nextTick(() => {
dialog.setData({ show: true });
});
queue.push(dialog);
} else {
console.warn(
'未找到 van-dialog 节点,请确认 selector 及 context 是否正确'
);
}
}
);
};
Dialog.alert = (options: DialogOptions) => Dialog(options);
Dialog.confirm = (options: DialogOptions) =>
Dialog({
showCancelButton: true,
...options,
});
Dialog.close = () => {
queue.forEach((dialog) => {
dialog.close();View on GitHub (pinned to 7a7d43757e)
Solutions
- Add <van-dialog id="van-dialog" /> to the WXML of the page (or component, with matching context) that calls Dialog.alert/Dialog.confirm, and register the component in its JSON ("van-dialog": "@vant/weapp/dialog/index").
- If you renamed the node, pass the matching selector, e.g. Dialog.alert({ selector: '#my-dialog', ... }).
- If the <van-dialog> node lives in a child component, pass options.context pointing at the instance that directly contains it, e.g. Dialog.alert({ context: () => this.selectComponent('#child') }) or context: this when inside a component.
- Defer the call until the page is rendered (wx.nextTick or after first render) if you call it during onLoad/onAttach before selectComponent can resolve.
- Wrap awaits in a timeout/race guard, since on this path the Promise never settles and awaiting code hangs silently.
Example fix
// before: page.ts
onLoad() {
Dialog.confirm({ message: 'Delete?' }); // warns, promise never settles
}
// after: page.wxml adds the node
<van-dialog id="van-dialog" show="{{ false }}" />
// page.ts
onReady() {
Dialog.confirm({ message: 'Delete?' });
} Defensive patterns
Strategy: validation
Validate before calling
function assertDialogNode(context?: object, selector = '#van-dialog') {
const ctx = context || getCurrentPages()[getCurrentPages().length - 1];
if (!ctx || !ctx.selectComponent || !ctx.selectComponent(selector)) {
throw new Error(
`<van-dialog ${selector}> not found in target context. Add <van-dialog id="van-dialog" /> to the page WXML and register it in usingComponents.`
);
}
}
// call before Dialog.alert/confirm:
// assertDialogNode(this, '#van-dialog'); Type guard
function hasSelectComponent(
ctx: unknown
): ctx is { selectComponent: (s: string) => WechatMiniprogram.Component.TrivialInstance | null } {
return (
!!ctx &&
typeof (ctx as any).selectComponent === 'function' &&
!!(ctx as any).selectComponent('#van-dialog')
);
} Try / catch
try {
await Promise.race([
Dialog.confirm({ message: 'Delete?' }),
new Promise((_, rej) => setTimeout(() => rej(new Error('dialog node missing / never resolved')), 5000)),
]);
} catch (e) {
console.warn('Dialog failed or node missing:', e);
} Prevention
- Always declare <van-dialog id="van-dialog" /> in every page WXML that uses the imperative Dialog API; keep a project snippet/checklist for it.
- If using a custom selector, make the id and options.selector match exactly (case-sensitive, include the leading '#').
- When the node is inside a child component, pass options.context referencing the instance that directly contains it, and resolve function contexts yourself.
- Never rely on Dialog()'s promise settling on the failure path — race it with a timeout when awaiting.
- After upgrading Vant Weapp, re-verify component registration names in usingComponents ('@vant/weapp/dialog/index').
When it happens
Trigger: Calling Dialog.alert(options) or Dialog.confirm(options) while (1) the page WXML lacks <van-dialog id="van-dialog" />, (2) options.selector points to an id that doesn't exist (e.g. selector: '#my-dialog' with no matching id), (3) options.context points to a page/component instance that does not contain the <van-dialog> node (e.g. dialog declared inside a child component but no context passed, or a function context returning the wrong instance), or (4) Dialog is called before the page tree is attached (e.g. in onLoad before initial render completes on some platforms).
Common situations: Forgetting to add <van-dialog id="van-dialog" /> to the page that calls Dialog.alert; placing the dialog node inside a custom component but calling Dialog from the page without passing context: () => this.selectComponent('#the-child'); using with-function contexts (share pages, custom-tab-bar pages) where getCurrentPages()'s top page isn't the one declaring the node; copy-pasting the default selector '#van-dialog' while giving the node a different id; abstract/factory pages generated dynamically where WXML wasn't updated after adding the API call.
Related errors
AI-assisted analysis of youzan/vant-weapp@7a7d43757e (2026-09-02).
Data as JSON: /api/errors/1abda8023ab6b220.
Report an issue: GitHub.