Meituan-Dianping/mpvue · error
Invalid Component definition: ${String(Ctor)}
Error message
Invalid Component definition: ${String(Ctor)} What it means
During vnode creation, after resolving aliases and `asyncComponent` handling, Vue requires the component option to be a constructor function or an async component factory. If `Ctor` is still not a function, Vue warns with the stringified value and aborts rendering that component.
Source
Thrown at packages/weex-vue-framework/factory.js:3548
children,
tag
) {
if (isUndef(Ctor)) {
return
}
var baseCtor = context.$options._base;
// plain options object: turn it into a constructor
if (isObject(Ctor)) {
Ctor = baseCtor.extend(Ctor);
}
// if at this stage it's not a constructor or an async component factory,
// reject.
if (typeof Ctor !== 'function') {
if (process.env.NODE_ENV !== 'production') {
warn(("Invalid Component definition: " + (String(Ctor))), context);
}
return
}
// async component
var asyncFactory;
if (isUndef(Ctor.cid)) {
asyncFactory = Ctor;
Ctor = resolveAsyncComponent(asyncFactory, baseCtor, context);
if (Ctor === undefined) {
// return a placeholder node for async component, which is rendered
// as a comment node but preserves all the raw information for the node.
// the information will be used for async server-rendering and hydration.
return createAsyncPlaceholder(
asyncFactory,
data,
context,
children,View on GitHub (pinned to 6c5d78ee04)
Solutions
- Log `String(Ctor)`/the variable to see what was actually passed (usually `undefined`), then fix the import/registration.
- Register the component: `components: { myComp }` locally or `Vue.component('my-comp', MyComp)` globally.
- For dynamic components, pass a real options object to `:is` only with `Vue.extend(obj)` or ensure it resolves via `resolveComponent`.
- Check circular imports and import timing; use `defineAsyncComponent`/`() => import(...)` for async loading.
Example fix
// before
import Comp from 'my-lib'; // no default export -> undefined
components: { Comp }
// after
import { Comp } from 'my-lib';
components: { Comp } Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof MyComp !== 'function') {
throw new TypeError(`Invalid component: ${String(MyComp)} — check import/registration`);
} Type guard
function isValidComponent(Ctor) {
return typeof Ctor === 'function' || (Ctor && typeof Ctor.render === 'function' && Ctor.cid);
} Prevention
- Verify imports resolve (named vs default) before registering.
- Keep a components index file to avoid circular-import undefineds.
- Type dynamic `:is` values as `Component` and validate at runtime in dev.
When it happens
Trigger: Passing a component definition object where a registered/constructor component is expected (e.g. `components: { x: { ... } }` but referencing it with `:is="someObject"` incorrectly), `Vue.component('x', undefined)` then using `<x/>`, a failed default/named import (`import X from 'lib'` where lib has no default, so X is undefined), or passing a string name never registered via `components`.
Common situations: Typo in component registration vs. usage; circular imports yielding `undefined` at module-eval time; mixing Vue 2 object-syntax components into `:is` bindings; dynamic `resolveComponent` on an unregistered tag.
Related errors
- $props is readonly.
- Avoid mutating an injected value directly since the changes
- Injection "${key}" not found
- Avoid using observed data object as vnode data: ${JSON.strin
- Avoid using non-primitive value as key, use string/number va
AI-assisted analysis of Meituan-Dianping/mpvue@6c5d78ee04 (2026-09-02).
Data as JSON: /api/errors/5aba525c26f65b28.
Report an issue: GitHub.