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}, BrowserUtils: ${GitHash}

What it means

The BrowserUtils module compares the loader's runtimeBuildInfo.gitHash against its own compiled-in GitHash constant (imported from consts:gitHash). A mismatch means the utils JS bundle and the runtime/loader were built from different source revisions, which would break the internal ABI, so init aborts.

Source

Thrown at src/native/libs/System.Native.Browser/utils/index.ts:31

    zeroRegion,
    arrayBufferNeedsCopy,
    viewOrCopy,
} from "./memory";
import { stringsInit, stringToUTF16, stringToUTF16Ptr, stringToUTF8, stringToUTF8Ptr, utf16ToString, utf8ToStringRelaxed } from "./strings";
import { abortPosix, getExitStatus } from "./host";
import { dotnetUpdateInternals, dotnetUpdateInternalsSubscriber } from "../utils/cross-module";
import { initPolyfills } from "../utils/polyfills";
import { registerRuntime } from "./runtime-list";
import { registerCDAC } from "./cdac";
import { abortBackgroundTimers, runBackgroundTimers } from "./scheduling";

export function dotnetInitializeModule(internals: InternalExchange): void {
    if (!Array.isArray(internals)) throw new Error("Expected internals to be an array");
    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}, BrowserUtils: ${GitHash}`);
    }

    initPolyfills();
    stringsInit();
    registerRuntime(runtimeApi);
    registerCDAC(runtimeApi);

    if (!Array.isArray(internals)) throw new Error("Expected internals to be an array");
    const runtimeApiLocal: Partial<RuntimeAPI> = {
        setHeapB32, setHeapB8, setHeapU8, setHeapU16, setHeapU32, setHeapI8, setHeapI16, setHeapI32, setHeapI52, setHeapU52, setHeapI64Big, setHeapF32, setHeapF64,
        getHeapB32, getHeapB8, getHeapU8, getHeapU16, getHeapU32, getHeapI8, getHeapI16, getHeapI32, getHeapI52, getHeapU52, getHeapI64Big, getHeapF32, getHeapF64,
        localHeapViewI8, localHeapViewI16, localHeapViewI32, localHeapViewI64Big, localHeapViewU8, localHeapViewU16, localHeapViewU32, localHeapViewF32, localHeapViewF64,
    };
    Object.assign(runtimeApi, runtimeApiLocal);

    internals[InternalExchangeIndex.BrowserUtilsExportsTable] = browserUtilsExportsToTable({
        utf16ToString,
        stringToUTF16,

View on GitHub (pinned to 290d5ab72c)

Solutions

  1. Clean rebuild + republish so the utils bundle and runtime share the same git hash/SDK.
  2. Cache-bust all dotnet artifacts together — versioned folder or content-hash in URL.
  3. Verify no service worker/CDN is serving a stale utils.js alongside a new runtime.

Example fix

// before: utils.js cached at v7 while runtime is v8
// after: bust cache, serve all from /8.0.x/
Defensive patterns

Strategy: validation

Validate before calling

const loaderHash = runtimeApi.runtimeBuildInfo?.gitHash;
if (loaderHash && loaderHash !== GitHash) {
  throw new Error("Refusing init: BrowserUtils/runtime git hash mismatch — republish with a matching build");
}

Try / catch

try { dotnetInitializeModule(internals); }
catch (e) {
  if (/Mismatched git hashes/.test(e.message)) purgeCacheAndReload();
  else throw e;
}

Prevention

When it happens

Trigger: Loading a BrowserUtils bundle (utils JS) from one commit while the runtime/loader carries a different runtimeBuildInfo.gitHash.

Common situations: Partial deploy of dotnet bundles; CDN/browser cache mixing old and new utils+runtime; local dev across repos with mismatched builds.

Related errors


AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06). Data as JSON: /api/errors/5e239455083c0aad. Report an issue: GitHub.