dotnet/runtime · error · Error
Native module already loaded
Error message
Native module already loaded
What it means
Thrown by libSystem.Native.Browser.extpost.js's dotnetInitializeModule when dotnetNativeModuleLoaded is already true. The native module is a singleton that may be initialized only once per page load; a second init attempt indicates the runtime bootstrap was invoked twice.
Source
Thrown at src/native/libs/System.Native.Browser/libSystem.Native.Browser.extpost.js:9
//
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
/* eslint-disable no-undef */
/* eslint-disable @typescript-eslint/no-unused-vars */
var fetch = fetch || undefined; var dotnetNativeModuleLoaded = false; var dotnetInternals = null;
export function dotnetInitializeModule(internals) {
if (dotnetNativeModuleLoaded) throw new Error("Native module already loaded");
dotnetNativeModuleLoaded = true;
if (!Array.isArray(internals)) throw new Error("Expected internals to be an array");
dotnetInternals = internals;
const runtimeApi = internals[0/*InternalExchangeIndex.RuntimeAPI*/];
if (typeof runtimeApi !== "object") throw new Error("Expected internals to have RuntimeAPI");
if (typeof runtimeApi.Module !== "object") throw new Error("Expected internals to have Module");
return createDotnetRuntime(runtimeApi.Module);
}
View on GitHub (pinned to 290d5ab72c)
Solutions
- Initialize the runtime exactly once, guarded by a module-level singleton flag.
- Reuse the existing runtime instance across components instead of re-creating it.
- Exclude the runtime bootstrap from HMR / StrictMode double-invoke.
Example fix
// before: effect boots the runtime on every mount (StrictMode fires twice)
useEffect(() => { dotnet.create(); }, []);
// after: cache the promise so init runs once
let runtimePromise;
function getRuntime() {
if (!runtimePromise) runtimePromise = dotnet.create();
return runtimePromise;
}
useEffect(() => { getRuntime(); }, []); Defensive patterns
Strategy: validation
Validate before calling
// Cache the runtime bootstrap so init runs exactly once
let runtimePromise;
function getRuntime() {
if (!runtimePromise) runtimePromise = dotnet.create();
return runtimePromise;
}
// all callers: await getRuntime(); Try / catch
try { await getRuntime(); }
catch (e) {
if (/Native module already loaded/.test(String(e.message))) {
// ignore: a concurrent caller already booted the runtime
return getRuntime();
}
throw e;
} Prevention
- Bootstrap the runtime through a single cached promise so repeated callers share one init.
- Exclude the bootstrap from React StrictMode double-invoke and HMR re-runs.
- Do not call dotnet.create() from multiple components independently.
When it happens
Trigger: Calling dotnet.create() (or the underlying dotnetInitializeModule) a second time in the same page/process, or importing/bootstrapping the runtime module twice.
Common situations: React StrictMode double-invoking an effect that boots the runtime; Vite/webpack HMR re-running the bootstrap; two components each calling dotnet.create(); a retry path that re-inits after a partial failure.
Related errors
- Failed on mono_wasm_get_dbg_command_info
- Failed to initialize ICU data
- Mismatched git hashes between loader and runtime. Loader: ${
- Invalid runtime config, cannot initialize the runtime.
- startup diagnostic client already registered
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/ac1edc9ddd393186.
Report an issue: GitHub.