dotnet/runtime · critical · Error

Mismatched git hashes between loader and runtime. Loader

Error message

Mismatched git hashes between loader and runtime. Loader: ${runtimeApi.runtimeBuildInfo.gitHash}, BrowserHost: ${GitHash}

What it means

Thrown by dotnetInitializeModule() (src/native/libs/Common/JavaScript/host/index.ts:13). The BrowserHost module is compiled with consts:gitHash, and the loader hands its own runtimeBuildInfo.gitHash in the InternalExchange. If both are non-empty and differ, the host refuses to wire exports because a loader/runtime build mismatch can corrupt the ABI.

Solutions

  1. Use all runtime assets (loader dotnet.runtime.js, native dotnet.js, dotnet.wasm) from the same SDK/runtime build.
  2. Clear the browser cache and re-publish so the gitHash-bearing files are consistent.
  3. If building locally, ensure the loader and the native host module are produced in the same build.

Example fix

<!-- before: loader from SDK A, native host from SDK B -->
<script src="_framework/dotnet.runtime.js" from SDK A></script>

<!-- after: re-publish with a single SDK so all _framework/* files share one gitHash -->
dotnet publish -c Release
Defensive patterns

Strategy: validation

Validate before calling

function loaderMatchesHost(loaderHash: string, hostHash: string): boolean {
  return !loaderHash || !hostHash || loaderHash === hostHash;
}

Prevention

When it happens

Trigger: dotnetInitializeModule(internals) reads internals[RuntimeAPI].runtimeBuildInfo.gitHash and compares to the compiled-in GitHash. A non-empty mismatch throws before any exports are registered.

Common situations: Using a dotnet.runtime.js (loader) from one build/SDK and a dotnet.js / BrowserHost from another; partial package upgrade where some runtime files were cached; mixing a locally built runtime with an SDK-published loader.

Related errors


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

Appendix: source

Thrown at src/native/libs/Common/JavaScript/host/index.ts:22

import type { InternalExchange, BrowserHostExports, RuntimeAPI, BrowserHostExportsTable, LoaderConfigInternal } from "./types";
import { InternalExchangeIndex } from "./types";
import { _ems_ } from "../ems-ambient";

import GitHash from "consts:gitHash";

import { runMain, runMainAndExit, initializeCoreCLR } from "./host";
import { registerPdbBytes, instantiateWebcilModule, registerDllBytes, installVfsFile, loadIcuData, instantiateWasm, } from "./assets";

export function dotnetInitializeModule(internals: InternalExchange): void {
    if (!Array.isArray(internals)) throw new Error("Expected internals to be an array");
    const runtimeApiLocal: Partial<RuntimeAPI> = {
        runMain,
        runMainAndExit,
    };
    const runtimeApi = internals[InternalExchangeIndex.RuntimeAPI];
    if (typeof runtimeApi !== "object") throw new Error("Expected internals to have RuntimeAPI");
    if (runtimeApi.runtimeBuildInfo.gitHash && runtimeApi.runtimeBuildInfo.gitHash !== GitHash) {
        throw new Error(`Mismatched git hashes between loader and runtime. Loader: ${runtimeApi.runtimeBuildInfo.gitHash}, BrowserHost: ${GitHash}`);
    }
    Object.assign(runtimeApi, runtimeApiLocal);

    internals[InternalExchangeIndex.BrowserHostExportsTable] = browserHostExportsToTable({
        registerDllBytes,
        installVfsFile,
        loadIcuData,
        initializeCoreCLR,
        registerPdbBytes,
        instantiateWasm,
        instantiateWebcilModule,
    });
    _ems_.dotnetUpdateInternals(internals, _ems_.dotnetUpdateInternalsSubscriber);

    setupEmscripten();

    function browserHostExportsToTable(map: BrowserHostExports): BrowserHostExportsTable {
        // keep in sync with browserHostExportsFromTable()

View on GitHub (pinned to 60108ba66e)