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}, Runtime: ${GitHash} What it means
The interop module compares the loader's runtimeBuildInfo.gitHash against its own compiled-in GitHash constant (consts:gitHash). A mismatch means the interop JS bundle and the runtime/loader were built from different source revisions, which would break the JSImport/marshaler ABI, so initialization aborts.
Source
Thrown at src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/index.ts:36
import { cancelPromise } from "./cancelable-promise";
import { loadLazyAssembly, loadSatelliteAssemblies } from "./lazy";
import { jsInteropState } from "./marshal";
import { initializeScheduling, abortInteropTimers } from "./scheduling";
import { wsAbort, wsClose, wsCreate, wsGetState, wsOpen, wsReceive, wsSend } from "./web-socket";
import {
httpSupportsStreamingRequest, httpSupportsStreamingResponse, httpCreateController, httpGetResponseType,
httpGetResponseStatus, httpAbort, httpTransformStreamWrite, httpTransformStreamClose, httpFetch,
httpFetchStream, httpFetchBytes, httpGetResponseHeaderNames, httpGetResponseHeaderValues, httpGetResponseBytes,
httpGetResponseLength, httpGetStreamedResponseBytes,
} from "./http";
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}, Runtime: ${GitHash}`);
}
const runtimeApiLocal: Partial<RuntimeAPI> = {
getAssemblyExports,
setModuleImports,
};
Object.assign(runtimeApi, runtimeApiLocal);
Object.assign(runtimeApi.INTERNAL, {
hasProperty,
getTypeOfProperty,
getProperty,
setProperty,
getGlobalThis,
getDotnetInstance,
dynamicImport,
bindCsFunction,
loadSatelliteAssemblies,
loadLazyAssembly,View on GitHub (pinned to 290d5ab72c)
Solutions
- Clean rebuild + republish so the interop bundle and runtime share the same git hash/SDK.
- Cache-bust all dotnet artifacts together — versioned folder or content-hash in URL.
- Verify no service worker/CDN is serving a stale interop.js alongside a new runtime.
Example fix
// before: interop.js cached at v7 while runtime is v8 // after: bust cache, serve all bundles 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: interop/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
- Serve all dotnet bundles from one versioned folder.
- Purge CDN/service-worker caches on every release.
- Validate git-hash agreement before init in custom hosts.
When it happens
Trigger: Loading an interop bundle from one commit while the runtime/loader carries a different runtimeBuildInfo.gitHash.
Common situations: Partial deploy of dotnet bundles; CDN/browser cache mixing an old interop.js with a new runtime; local dev across repos with mismatched builds.
Related errors
- Mismatched git hashes between loader and runtime. Loader: ${
- Mismatched git hashes between loader and runtime. Loader: ${
- Mismatched git hashes between loader and runtime. Loader: ${
- Mismatched git hashes between loader and runtime. Loader: ${
- Failed to load resource '${asset.name}' from '${asset.resolv
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/9e6472c6fc9bb250.
Report an issue: GitHub.