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

  1. 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").
  2. If you renamed the node, pass the matching selector, e.g. Dialog.alert({ selector: '#my-dialog', ... }).
  3. 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.
  4. 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.
  5. 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

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.