{"record":{"id":"c607e1fec8e13c54","repo":"dotnet/runtime","slug":"can-t-use-modulefactory-callback-of-createdotnetru","errorCode":null,"errorMessage":"Can't use moduleFactory callback of createDotnetRuntime function.","messagePattern":"Can't use moduleFactory callback of createDotnetRuntime function\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mono/browser/runtime/loader/run.ts","lineNumber":308,"sourceCode":"    emscriptenPrepared = true;\n    if (ENVIRONMENT_IS_WEB && loaderHelpers.config.forwardConsole && typeof globalThis.WebSocket != \"undefined\") {\n        setup_proxy_console(\"main\", globalThis.console, globalThis.location.origin);\n    }\n    mono_assert(emscriptenModule, \"Null moduleConfig\");\n    mono_assert(loaderHelpers.config, \"Null moduleConfig.config\");\n\n    // extract ModuleConfig\n    if (typeof moduleFactory === \"function\") {\n        const extension = moduleFactory(globalObjectsRoot.api) as any;\n        if (extension.ready) {\n            throw new Error(\"Module.ready couldn't be redefined.\");\n        }\n        Object.assign(emscriptenModule, extension);\n        deep_merge_module(emscriptenModule, extension);\n    } else if (typeof moduleFactory === \"object\") {\n        deep_merge_module(emscriptenModule, moduleFactory);\n    } else {\n        throw new Error(\"Can't use moduleFactory callback of createDotnetRuntime function.\");\n    }\n\n    await detect_features_and_polyfill(emscriptenModule);\n}\n\nexport async function createEmscripten (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)): Promise<RuntimeAPI | EmscriptenModuleInternal> {\n    await prepareEmscripten(moduleFactory);\n\n    if (BuildConfiguration === \"Debug\" && !ENVIRONMENT_IS_WORKER) {\n        mono_log_info(`starting script ${loaderHelpers.scriptUrl}`);\n        mono_log_info(`starting in ${loaderHelpers.scriptDirectory}`);\n    }\n    if (loaderHelpers.config.exitOnUnhandledError) {\n        installUnhandledErrorHandler();\n    }\n\n    registerEmscriptenExitHandlers();\n","sourceCodeStart":290,"sourceCodeEnd":326,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/mono/browser/runtime/loader/run.ts#L290-L326","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (string passed by mistake)\nconst api = await createDotnetRuntime('./dotnet.config.json');\n\n// after (parsed object)\nconst config = await fetch('./dotnet.config.json').then(r => r.json());\nconst api = await createDotnetRuntime(config);","handlingStrategy":"type-guard","validationCode":"// Validate moduleFactory type before calling createDotnetRuntime\nfunction validateModuleFactory(factory: unknown) {\n  if (typeof factory !== 'function' && (typeof factory !== 'object' || factory === null)) {\n    throw new TypeError('moduleFactory must be a function or a config object');\n  }\n}\nvalidateModuleFactory(myConfig);","typeGuard":"function isModuleFactory(factory: unknown): factory is Function | object {\n  return typeof factory === 'function' || (typeof factory === 'object' && factory !== null);\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["api-misuse","configuration","typescript","startup"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}