Meituan-Dianping/mpvue · warning
Avoid using non-primitive value as key, use string/number va
Error message
Avoid using non-primitive value as key, use string/number value instead.
What it means
Vue uses list keys to match old and new vnodes during patching. A non-primitive key (object/array) cannot be compared reliably, so Vue warns that the key is useless and falls back to treating it as undefined, causing inefficient or incorrect list updates.
Source
Thrown at src/core/vdom/create-element.js:72
`Avoid using observed data object as vnode data: ${JSON.stringify(data)}\n` +
'Always create fresh vnode data objects in each render!',
context
)
return createEmptyVNode()
}
// object syntax in v-bind
if (isDef(data) && isDef(data.is)) {
tag = data.is
}
if (!tag) {
// in case of component :is set to falsy value
return createEmptyVNode()
}
// warn against non-primitive key
if (process.env.NODE_ENV !== 'production' &&
isDef(data) && isDef(data.key) && !isPrimitive(data.key)
) {
warn(
'Avoid using non-primitive value as key, ' +
'use string/number value instead.',
context
)
}
// support single function children as default scoped slot
if (Array.isArray(children) &&
typeof children[0] === 'function'
) {
data = data || {}
data.scopedSlots = { default: children[0] }
children.length = 0
}
if (normalizationType === ALWAYS_NORMALIZE) {
children = normalizeChildren(children)
} else if (normalizationType === SIMPLE_NORMALIZE) {
children = simpleNormalizeChildren(children)
}View on GitHub (pinned to 6c5d78ee04)
Solutions
- Key by a primitive identifier: `:key="item.id"`
- If no id exists, key by index `:key="index"` (accepting reorder caveats) or generate a stable string key
- Ensure objects carry a unique primitive field you can use as key
Example fix
// before
<li v-for="item in items" :key="item">{{ item.name }}</li>
// after
<li v-for="item in items" :key="item.id">{{ item.name }}</li> Defensive patterns
Strategy: validation
Validate before calling
function assertPrimitiveKeys (items, keyOf) {
const bad = items.filter(it => {
const k = keyOf(it)
return k != null && (typeof k !== 'string' && typeof k !== 'number' && typeof k !== 'symbol')
})
if (bad.length) throw new TypeError('non-primitive v-for keys: ' + bad.length + ' item(s)')
} Type guard
function isPrimitiveKey (k) {
return k === null || (typeof k !== 'object' && typeof k !== 'function')
} Prevention
- Always key lists by a primitive id field
- Never pass whole objects as :key
- Use index keys only as a last resort for static lists
- Lint for :key="item" patterns in v-for
When it happens
Trigger: Rendering a v-for / list of vnodes with `:key="item"` or `h('li', { key: item }, ...)` where `item` is an object rather than a string/number.
Common situations: Using whole API objects as keys; forgetting to key by `item.id`; iterating over arrays of objects in render functions or v-for.
Related errors
- Avoid using non-primitive value as key, use string/number va
- <template> cannot be keyed. Place the key on real elements i
- <transition-group> children must be keyed: <${name}>
- Invalid v-for expression: ${exp}
- `key` does not work on <slot> because slots are abstract out
AI-assisted analysis of Meituan-Dianping/mpvue@6c5d78ee04 (2026-09-02).
Data as JSON: /api/errors/077859f7c684b5a2.
Report an issue: GitHub.