dotnet/runtime · error · Error
Module.ready couldn't be redefined.
Error message
Module.ready couldn't be redefined.
What it means
Thrown by prepareEmscripten when the moduleFactory callback returns an object that has a `ready` property. The Emscripten module's `ready` field is reserved/managed internally by the runtime, so the runtime refuses to let user config redefine it.
Source
Thrown at src/mono/browser/runtime/loader/run.ts:301
}
let emscriptenPrepared = false;
async function prepareEmscripten (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) {
if (emscriptenPrepared) {
return;
}
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}`);View on GitHub (pinned to 290d5ab72c)
Solutions
- Remove the `ready` property from the config object returned by your moduleFactory callback.
- If you need a ready signal, use the returned RuntimeAPI promise (await createDotnetRuntime(...)) or the runtime's ready event instead of setting Module.ready.
- Pass only supported DotnetModuleConfig keys in the callback.
Example fix
// before: factory returns config with ready
// createDotnetRuntime(() => ({ ready: myPromise, config: {...} }));
// after: drop ready; use the returned promise
const dotnet = await createDotnetRuntime(() => ({ config: {...} }));
// dotnet is ready once the promise resolves Defensive patterns
Strategy: validation
Validate before calling
const factory = () => {
const cfg = { config: monoConfig };
delete (cfg as any).ready; // never return ready
return cfg;
}; Type guard
function configHasNoReady(cfg: any): boolean {
return cfg == null || typeof cfg !== 'object' || !('ready' in cfg);
} Prevention
- Never set Module.ready in user config; rely on the createDotnetRuntime promise instead.
- Audit config objects copied from Emscripten samples before passing them in.
- Only pass documented DotnetModuleConfig keys.
When it happens
Trigger: Produced when createDotnetRuntime is called with a moduleFactory function whose returned config object includes a `ready` key (e.g. { ready: ... }).
Common situations: Copying an Emscripten-style config that sets Module.ready; migrating from a raw Emscripten setup into the dotnet runtime builder; a third-party wrapper that injects ready.
Related errors
- Can't use moduleFactory callback of createDotnetRuntime func
- Unexpected behavior ${asset.behavior} of asset ${asset.name}
- Missing window to the query parameters from
- URLSearchParams is supported
- .NET runtime has failed to start, because too much memory wa
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/1c60352ed7de9a2a.
Report an issue: GitHub.