vuejs/core · error · Error
Invalid async component load result: ${comp}
Error message
Invalid async component load result: ${comp} What it means
Thrown in __DEV__ by defineAsyncComponent's loader when the resolved value is truthy but is neither a plain object nor a function. After interop unwrapping (esModule default / Module toStringTag), a valid Vue component must be an options object or a render function. apiAsyncComponent.ts:112 aborts because the loader returned a non-component value (e.g. a string, number, array, or a Promise).
Source
Thrown at packages/runtime-core/src/apiAsyncComponent.ts:112
.then((comp: any) => {
if (thisRequest !== pendingRequest && pendingRequest) {
return pendingRequest
}
if (__DEV__ && !comp) {
warn(
`Async component loader resolved to undefined. ` +
`If you are using retry(), make sure to return its return value.`,
)
}
// interop module default
if (
comp &&
(comp.__esModule || comp[Symbol.toStringTag] === 'Module')
) {
comp = comp.default
}
if (__DEV__ && comp && !isObject(comp) && !isFunction(comp)) {
throw new Error(`Invalid async component load result: ${comp}`)
}
resolvedComp = comp
return comp
}))
)
}
return defineComponent({
name: 'AsyncComponentWrapper',
__asyncLoader: load,
__asyncHydrate(el, instance, hydrate) {
const wasConnected = el.isConnected
let patched = false
;(instance.bu || (instance.bu = [])).push(() => (patched = true))
const performHydrate = () => {
// skip hydration if the component has been patchedView on GitHub (pinned to a2b40db9a8)
Solutions
- Verify the loader actually imports a Vue component: check that the module's default export is an options object or a function.
- If using named exports, return the correct binding, e.g. `() => import('./MyComp.vue').then(m => m.MyComp)`.
- Ensure retry()/onError handlers return their value so the resolved value stays a component (the related 'resolved to undefined' warn at line 99 covers that case).
- Add a runtime type check in the loader and map non-components to a real component or a thrown error.
Example fix
// before
const AsyncComp = defineAsyncComponent(() => import('./config.json'))
// after
const AsyncComp = defineAsyncComponent(() => import('./RealComponent.vue')) Defensive patterns
Strategy: type-guard
Validate before calling
// Validate the loader's resolved value before registering the async component.
function isComponent(v: unknown): boolean {
return (typeof v === 'object' && v !== null) || typeof v === 'function'
}
const loader = async () => {
const mod = await import('./MyComp.vue')
const comp = mod?.__esModule ? mod.default : mod
if (!isComponent(comp)) {
throw new Error(`async loader resolved to non-component: ${comp}`)
}
return comp
}
defineAsyncComponent(loader) Type guard
function isVueComponent(v: unknown): v is object | ((...a: any[]) => any) {
return (typeof v === 'object' && v !== null) || typeof v === 'function'
} Prevention
- Point dynamic imports at actual .vue components, not arbitrary modules.
- If using named exports, map them in the loader: `.then(m => m.NamedComp)`.
- Return values from retry()/onError handlers so the resolved value stays a component.
When it happens
Trigger: An async loader whose import returns a non-component — e.g. `() => import('./constants')` where the module exports a string/number; a dynamic import of a .json or a non-Vue module; a loader that forgets `.default` after an interop edge case; returning a Promise-of-Promise that resolves to a raw value.
Common situations: Typo in the import path pointing at a non-component module; misconfigured dynamic import in a route config; a barrel re-export that swaps a component for a plain value; tree-shaking that leaves a module exporting a non-component default.
Related errors
- ${key} compat has been disabled.
- [@vue/compiler-core] decodeEntities option is required in br
- [@vue/compiler-sfc] <script> and <script setup> must have th
- [@vue/compiler-sfc] SFC contains no <script> tags.
- [@vue/compiler-sfc] `modules` option is not supported in the
AI-assisted analysis of vuejs/core@a2b40db9a8 (2026-08-12).
Data as JSON: /api/errors/8c4c4afbf1107d24.
Report an issue: GitHub.