OrchardCMS/OrchardCore · error · Error
Invalid async component load result
Error message
Invalid async component load result: ${comp} What it means
Vue 2.7's async component factory (used by Vue.component(name, () => import(...)) / defineAsyncComponent-style loaders in the CommonJS dev build) validates the resolved module after the dynamic import/load: after unwrapping an ES-module default, the result must be an object (component options) or a function (functional component). Anything else (undefined, a string, null wrapper values, wrong export) triggers this Error, with `comp` interpolated into the message.
Solutions
- Ensure the dynamically loaded module's default export (or the named export you point at) is a valid component options object or function.
- If the module exports the component as a named export, load it explicitly: () => import('./Comp.vue').then(m => m.Comp).
- Check bundler/TS interop settings (esModuleInterop, output module format) so comp.__esModule/Module unwrapping works.
- Log the loaded module in the loader to inspect its shape before returning it.
Example fix
// before
Vue.component('my-comp', () => import('./myComp')); // module has no default component
// after
Vue.component('my-comp', () =>
import('./myComp').then(m => m.default || m.MyComp)
); Defensive patterns
Strategy: type-guard
Validate before calling
function isValidComponent(comp) {
if (comp && (comp.__esModule || comp[Symbol.toStringTag] === 'Module')) comp = comp.default;
return comp != null && (typeof comp === 'object' || typeof comp === 'function');
}
// usage before registering: if (!isValidComponent(m)) console.warn('bad async component'); Type guard
function isComponentLike(v) { return v != null && (typeof v === 'object' || typeof v === 'function'); } Try / catch
Vue.component('x', function () {
return import('./x.vue')
.then(function (m) { return m.default || m; })
.catch(function (err) {
if (/Invalid async component load result/.test(err.message)) {
return FallbackComponent;
}
throw err;
});
}); Prevention
- Always default-export a component options object (or function) from dynamically imported files.
- Point loaders at the exact export: .then(m => m.NamedExport) for named exports.
- Keep bundler/TS interop settings (esModuleInterop) consistent so module-default unwrapping works.
- Log loader results once during setup to confirm the resolved shape.
When it happens
Trigger: A dynamic import resolves to a module whose default export is missing or not a component: () => import('./x') where x.js has no component default export; exporting a plain value/string instead of a component options object; mismatched module systems (ES module imported from CJS loader without __esModule/Module tag so the wrong shape survives interop).
Common situations: Migrating Vue 2 code that imported a component from a file that also re-exports constants (named vs default confusion); webpack/vite config changes that alter module format; TypeScript files compiled without esModuleInterop so comp.default is not unwrapped.
Related errors
- Invalid async component load result
- Invalid async component load result
- Invalid async component load result:
- Invalid async component load result:
- Standalone host is missing a <div id="media-gallery"> mount…
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/0251ce853c4e8925.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore.Modules/OrchardCore.Resources/wwwroot/Vendor/vue-2.7.16/vue.common.dev.js:3892
else {
throw err;
}
})
.then((comp) => {
if (thisRequest !== pendingRequest && pendingRequest) {
return pendingRequest;
}
if (!comp) {
warn$2(`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 (comp && !isObject(comp) && !isFunction(comp)) {
throw new Error(`Invalid async component load result: ${comp}`);
}
return comp;
})));
};
return () => {
const component = load();
return {
component,
delay,
timeout,
error: errorComponent,
loading: loadingComponent
};
};
}
function createLifeCycle(hookName) {
return (fn, target = currentInstance) => {View on GitHub (pinned to 4306c0717f)