OrchardCMS/OrchardCore · error · Error
Invalid async component load result
Error message
Invalid async component load result: ${comp} What it means
Vue 2.7's runtime-only CommonJS dev build (vue.runtime.common.dev.js) applies the same check in its async component loader: the value returned by the loader (after ES-module default interop) must be a component object or function; otherwise it throws `Invalid async component load result: ${comp}`. The runtime build has no compiler, so components must arrive as render-function-based options objects/functions.
Solutions
- Ensure loaded components are pre-compiled (render functions) or use the full build (vue.common.dev.js with compiler) if you rely on template strings.
- Return the component options object/function explicitly: () => import('./c.js').then(m => m.default).
- Check the webpack/vite `vue` alias — runtime-only vs compiler-included build mismatch is a common cause.
- Log the loader result to verify its shape before it reaches Vue's validation.
Example fix
// before
Vue.component('chart', () => import('./chart')); // chart.js default-exports { template: '<div/>' } with runtime-only build
// after
// Precompile: export default { render(h) { return h('div'); } }
Vue.component('chart', () => import('./chart').then(m => m.default)); Defensive patterns
Strategy: type-guard
Validate before calling
function assertRenderCapable(comp) {
if (comp && (comp.__esModule || comp[Symbol.toStringTag] === 'Module')) comp = comp.default;
if (!comp || (typeof comp !== 'object' && typeof comp !== 'function')) {
throw new Error('Async loader must resolve to component object/function');
}
return comp;
}
// usage: Vue.component('chart', () => import('./chart').then(assertRenderCapable)); Type guard
function hasRenderFn(c) { return c != null && typeof c === 'object' && typeof c.render === 'function'; } Try / catch
Vue.component('chart', () =>
import('./chart')
.then(m => m.default)
.catch(err => {
if (/Invalid async component load result/.test(String(err.message))) {
return { render: h => h('div', 'component failed to load') };
}
throw err;
})
); Prevention
- With the runtime-only build, ship pre-compiled components (render functions), not template strings.
- Verify the `vue` alias points at the intended build (runtime vs full) before debugging async components.
- Standardize one loader helper that unwraps module default and validates shape for all async components.
- Add a fallback component in loaders so a bad module degrades gracefully.
When it happens
Trigger: Async loader () => import('./c') where the module's default export is a string template or options lacking a render function in the runtime-only build; module resolved to a non-component export; CJS/ESM interop not applied so the raw namespace or wrong value is checked.
Common situations: Using the runtime-only build while components are defined with `template` strings resolved through loaders that return raw strings; mixed Vue 2.7 standalone (with compiler) and runtime builds in one app; webpack alias pointing vue to the runtime build unexpectedly.
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/258f54a0f94668cc.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore.Modules/OrchardCore.Resources/wwwroot/Vendor/vue-2.7.16/vue.runtime.common.dev.js:3173
else {
throw err;
}
})
.then((comp) => {
if (thisRequest !== pendingRequest && pendingRequest) {
return pendingRequest;
}
if (!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 (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)