dotnet/runtime · error · Error
Can't use moduleFactory callback of createDotnetRuntime…
Error message
Can't use moduleFactory callback of createDotnetRuntime function.
What it means
Thrown by prepareEmscripten() when the moduleFactory argument is neither a function nor an object (e.g., it is a number, string, boolean, null without falling through, or symbol). The createDotnetRuntime API only accepts these two shapes: a config object or a factory function that receives the RuntimeAPI and returns a config object. Any other type is a programming error.
Solutions
- Ensure the argument passed to createDotnetRuntime is either a DotnetModuleConfig object or a function returning one.
- If loading config from JSON, parse it first: createDotnetRuntime(JSON.parse(configString)).
- Check the argument type before calling: if (typeof config !== 'object' && typeof config !== 'function') throw new TypeError(...).
- Use the high-level dotnet.create() API instead of the low-level createDotnetRuntime to avoid manual module factory handling.
Example fix
// before (string passed by mistake)
const api = await createDotnetRuntime('./dotnet.config.json');
// after (parsed object)
const config = await fetch('./dotnet.config.json').then(r => r.json());
const api = await createDotnetRuntime(config); Defensive patterns
Strategy: type-guard
Validate before calling
// Validate moduleFactory type before calling createDotnetRuntime
function validateModuleFactory(factory: unknown) {
if (typeof factory !== 'function' && (typeof factory !== 'object' || factory === null)) {
throw new TypeError('moduleFactory must be a function or a config object');
}
}
validateModuleFactory(myConfig); Type guard
function isModuleFactory(factory: unknown): factory is Function | object {
return typeof factory === 'function' || (typeof factory === 'object' && factory !== null);
} Prevention
- Use TypeScript types (DotnetModuleConfig) to catch type errors at compile time.
- If loading config from a file, always parse JSON before passing.
- Prefer dotnet.create() over the low-level createDotnetRuntime to avoid manual factory handling.
When it happens
Trigger: Passing a non-object, non-function value as the moduleFactory argument to createDotnetRuntime() or createEmscripten(). For example passing null (after the emscriptenModule check), a string URL, a number, or a Boolean wrapper.
Common situations: Incorrectly wiring up the runtime in a bundler (webpack/rollup) where the import resolves to a string URL instead of a module config object. Passing a config JSON string instead of a parsed object. Accidentally passing undefined from a failed dynamic import.
Related errors
- Module.ready couldn't be redefined.
- Expected environment variable
- Expected runtimeOptions to be an array of strings
- Invalid config, resources is not set
- invariant globalization mode is inactive and no ICU data…
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/c607e1fec8e13c54.
Report an issue: GitHub.
Appendix: source
Thrown at src/mono/browser/runtime/loader/run.ts:308
emscriptenPrepared = true;
if (ENVIRONMENT_IS_WEB && loaderHelpers.config.forwardConsole && typeof globalThis.WebSocket != "undefined") {
setup_proxy_console("main", globalThis.console, globalThis.location.origin);
}
mono_assert(emscriptenModule, "Null moduleConfig");
mono_assert(loaderHelpers.config, "Null moduleConfig.config");
// extract ModuleConfig
if (typeof moduleFactory === "function") {
const extension = moduleFactory(globalObjectsRoot.api) as any;
if (extension.ready) {
throw new Error("Module.ready couldn't be redefined.");
}
Object.assign(emscriptenModule, extension);
deep_merge_module(emscriptenModule, extension);
} else if (typeof moduleFactory === "object") {
deep_merge_module(emscriptenModule, moduleFactory);
} else {
throw new Error("Can't use moduleFactory callback of createDotnetRuntime function.");
}
await detect_features_and_polyfill(emscriptenModule);
}
export async function createEmscripten (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)): Promise<RuntimeAPI | EmscriptenModuleInternal> {
await prepareEmscripten(moduleFactory);
if (BuildConfiguration === "Debug" && !ENVIRONMENT_IS_WORKER) {
mono_log_info(`starting script ${loaderHelpers.scriptUrl}`);
mono_log_info(`starting in ${loaderHelpers.scriptDirectory}`);
}
if (loaderHelpers.config.exitOnUnhandledError) {
installUnhandledErrorHandler();
}
registerEmscriptenExitHandlers();
View on GitHub (pinned to 60108ba66e)