Meituan-Dianping/mpvue · warning
<template> cannot be keyed. Place the key on real elements i
Error message
<template> cannot be keyed. Place the key on real elements instead.
What it means
A key binding was placed on a <template> element. Because <template> is an abstract wrapper that renders no element of its own (and v-for on template renders its children), a key there is meaningless; the compiler warns and points you to put the key on the real rendered elements instead.
Source
Thrown at packages/weex-template-compiler/build.js:1628
if (l) {
var attrs = el.attrs = new Array(l);
for (var i = 0; i < l; i++) {
attrs[i] = {
name: el.attrsList[i].name,
value: JSON.stringify(el.attrsList[i].value)
};
}
} else if (!el.pre) {
// non root node in pre blocks with no attributes
el.plain = true;
}
}
function processKey (el) {
var exp = getBindingAttr(el, 'key');
if (exp) {
if (process.env.NODE_ENV !== 'production' && el.tag === 'template') {
warn("<template> cannot be keyed. Place the key on real elements instead.");
}
el.key = exp;
}
}
function processRef (el) {
var ref = getBindingAttr(el, 'ref');
if (ref) {
el.ref = ref;
el.refInFor = checkInFor(el);
}
}
function processFor (el) {
var exp;
if ((exp = getAndRemoveAttr(el, 'v-for'))) {
var inMatch = exp.match(forAliasRE);
if (!inMatch) {View on GitHub (pinned to 6c5d78ee04)
Solutions
- Move the :key binding from <template> to the real root element(s) inside it
- If children have no single root, wrap them in a keyed real element
- Upgrade consideration: Vue 3 allows keys on template v-for, so this warning is Vue 2-specific
Example fix
// before
<template v-for="item in items" :key="item.id">
<li>{{ item.text }}</li>
</template>
// after
<template v-for="item in items">
<li :key="item.id">{{ item.text }}</li>
</template> Defensive patterns
Strategy: validation
Validate before calling
function keyOnTemplate(template) {
return /<template[^>]*\s(?::key|v-bind:key)\s*=/.test(template)
? 'key found on <template>; move it to real elements'
: null;
} Type guard
function hasNoTemplateKey(template) {
return typeof template === 'string' && !/<template[^>]*\s(?::key|v-bind:key|key)\s*=/.test(template);
} Prevention
- Put :key on real elements inside template v-for loops
- Add eslint-plugin-vue rule vue/require-v-for-key + no-use-v-if-with-v-for style checks
- Remember this is Vue 2 semantics; Vue 3 permits keyed template v-for
When it happens
Trigger: Using key with template, e.g. <template v-for="item in list" :key="item.id">...</template> — processKey detects el.tag === 'template' with a bound key in dev mode.
Common situations: Migrating list rendering code where the key belonged on an inner element, or applying :key habitually to every element with v-for including template wrappers (note: valid in Vue 3, warned in Vue 2).
Related errors
- Invalid v-for expression: ${exp}
- `key` does not work on <slot> because slots are abstract out
- tag <${tag}> has no matching end tag.
- Templates should only be responsible for mapping the state t
- v-${el.elseif ? ('else-if="' + el.elseif + '"') : 'else'} us
AI-assisted analysis of Meituan-Dianping/mpvue@6c5d78ee04 (2026-09-02).
Data as JSON: /api/errors/e75cd9709927d2cd.
Report an issue: GitHub.