dotnet/runtime · error · Error
Diag module already loaded
Error message
Diag module already loaded
What it means
Thrown by `setRuntimeGlobalsImpl` in the diagnostics globals when it is invoked a second time within the same runtime instance. The diagnostics module is initialised exactly once; the `_diagnosticModuleLoaded` flag guards against double initialisation, which would otherwise rebind the diagnostic helpers and corrupt the websocket handle map.
Source
Thrown at src/mono/browser/runtime/diagnostics/globals.ts:16
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
import type { DiagnosticHelpers, GlobalObjects, LoaderHelpers, RuntimeHelpers, DotnetModuleInternal } from "../types/internal";
export let _diagnosticModuleLoaded = false; // please keep it in place also as rollup guard
export let diagnosticHelpers: DiagnosticHelpers = null as any;
export let runtimeHelpers: RuntimeHelpers = null as any;
export let loaderHelpers: LoaderHelpers = null as any;
export let Module: DotnetModuleInternal = null as any;
export function setRuntimeGlobalsImpl (globalObjects: GlobalObjects): void {
if (_diagnosticModuleLoaded) {
throw new Error("Diag module already loaded");
}
_diagnosticModuleLoaded = true;
diagnosticHelpers = globalObjects.diagnosticHelpers;
runtimeHelpers = globalObjects.runtimeHelpers;
loaderHelpers = globalObjects.loaderHelpers;
Module = globalObjects.module;
}
View on GitHub (pinned to 60108ba66e)
Solutions
- Ensure `dotnet.createDotnetRuntime` (and thus `setRuntimeGlobals`) is called exactly once per page load.
- In tests, reset the module registry (or reload the iframe/Worker) between cases instead of re-initialising.
- Check for duplicate `<script>` tags or duplicate bundler imports of the diagnostics module.
Example fix
// before: createDotnetRuntime called twice await dotnet.createDotnetRuntime(opts1); await dotnet.createDotnetRuntime(opts2); // throws 'Diag module already loaded' // after: create once and reuse the runtime const runtime = await dotnet.createDotnetRuntime(opts1); // reuse `runtime` everywhere
Defensive patterns
Strategy: validation
Validate before calling
function canInitDiag () {
return !_diagnosticModuleLoaded;
}
if (canInitDiag()) setRuntimeGlobals(globalObjects); Type guard
function isDiagModuleFresh (): boolean {
return !_diagnosticModuleLoaded;
} Prevention
- Call `createDotnetRuntime` exactly once per page/Worker.
- Reload the Worker/iframe between tests that need a fresh runtime.
- Audit bundler chunks so the diagnostics module appears in only one.
When it happens
Trigger: Calling `setRuntimeGlobals(globalObjects)` (index.ts:21) twice — typically because `dotnet.createDotnetRuntime` was called twice, or because the diagnostics entry point was imported twice (e.g. via two script tags or duplicate bundler entries). The second call hits the guard at globals.ts:15-17.
Common situations: Loading `dotnet.diagnostics.js` more than once on a page; calling `createDotnetRuntime` twice in tests without reloading; bundler misconfiguration that includes the diagnostics module in two chunks.
Related errors
- startup diagnostic client already registered
- multiple clients in parallel are not allowed
- Native module already loaded
- Runtime is not running
- No active JS diagnostic session
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/3ebfdbbd2b4694be.
Report an issue: GitHub.