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

  1. Ensure `dotnet.createDotnetRuntime` (and thus `setRuntimeGlobals`) is called exactly once per page load.
  2. In tests, reset the module registry (or reload the iframe/Worker) between cases instead of re-initialising.
  3. 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

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


AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10). Data as JSON: /api/errors/3ebfdbbd2b4694be. Report an issue: GitHub.