Meituan-Dianping/mpvue · warning

`key` does not work on <slot> because slots are abstract out

Error message

`key` does not work on <slot> because slots are abstract outlets and can possibly expand into multiple elements. Use the key on a wrapping element instead.

What it means

A <slot> element received a key binding. Slots are abstract outlets that may expand into multiple elements, so a per-node key is meaningless; the compiler warns and suggests keying a wrapping real element instead.

Source

Thrown at packages/weex-template-compiler/build.js:1736

function addIfCondition (el, condition) {
  if (!el.ifConditions) {
    el.ifConditions = [];
  }
  el.ifConditions.push(condition);
}

function processOnce (el) {
  var once$$1 = getAndRemoveAttr(el, 'v-once');
  if (once$$1 != null) {
    el.once = true;
  }
}

function processSlot (el) {
  if (el.tag === 'slot') {
    el.slotName = getBindingAttr(el, 'name');
    if (process.env.NODE_ENV !== 'production' && el.key) {
      warn(
        "`key` does not work on <slot> because slots are abstract outlets " +
        "and can possibly expand into multiple elements. " +
        "Use the key on a wrapping element instead."
      );
    }
  } else {
    var slotTarget = getBindingAttr(el, 'slot');
    if (slotTarget) {
      el.slotTarget = slotTarget === '""' ? '"default"' : slotTarget;
    }
    if (el.tag === 'template') {
      el.slotScope = getAndRemoveAttr(el, 'scope');
    }
  }
}

function processComponent (el) {
  var binding;

View on GitHub (pinned to 6c5d78ee04)

Solutions

  1. Remove the key from <slot>
  2. Wrap the slot in a keyed real element (e.g. a keyed <div>) if re-render control is needed
  3. Place the key on the parent element that consumes the slot content

Example fix

// before
<slot :key="item.id">fallback</slot>
// after
<div :key="item.id"><slot>fallback</slot></div>
Defensive patterns

Strategy: validation

Validate before calling

function keyOnSlot(template) {
  return /<slot[^>]*\s(?::key|v-bind:key|key)\s*=/.test(template)
    ? 'key on <slot>; use a wrapping element instead'
    : null;
}

Type guard

function hasNoSlotKey(template) {
  return typeof template === 'string' && !/<slot[^>]*\s(?::key|v-bind:key|key)\s*=/.test(template);
}

Prevention

When it happens

Trigger: Writing <slot :key="x"> (or key="x") in a template — processSlot detects el.tag === 'slot' with el.key set in dev mode, typically after processKey has already assigned el.key.

Common situations: Keying slots inside v-for loops to force re-render, or habitually adding :key to every repeated element including <slot> placeholders.

Related errors


AI-assisted analysis of Meituan-Dianping/mpvue@6c5d78ee04 (2026-09-02). Data as JSON: /api/errors/7cf9da7dd2d6dfef. Report an issue: GitHub.