{"record":{"id":"9e6472c6fc9bb250","repo":"dotnet/runtime","slug":"mismatched-git-hashes-between-loader-and-runtime-9e6472","errorCode":null,"errorMessage":"Mismatched git hashes between loader and runtime. Loader: ${runtimeApi.runtimeBuildInfo.gitHash}, Runtime: ${GitHash}","messagePattern":"Mismatched git hashes between loader and runtime\\. Loader: (.+?), Runtime: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/index.ts","lineNumber":36,"sourceCode":"import { cancelPromise } from \"./cancelable-promise\";\nimport { loadLazyAssembly, loadSatelliteAssemblies } from \"./lazy\";\nimport { jsInteropState } from \"./marshal\";\nimport { initializeScheduling, abortInteropTimers } from \"./scheduling\";\nimport { wsAbort, wsClose, wsCreate, wsGetState, wsOpen, wsReceive, wsSend } from \"./web-socket\";\nimport {\n    httpSupportsStreamingRequest, httpSupportsStreamingResponse, httpCreateController, httpGetResponseType,\n    httpGetResponseStatus, httpAbort, httpTransformStreamWrite, httpTransformStreamClose, httpFetch,\n    httpFetchStream, httpFetchBytes, httpGetResponseHeaderNames, httpGetResponseHeaderValues, httpGetResponseBytes,\n    httpGetResponseLength, httpGetStreamedResponseBytes,\n} from \"./http\";\n\nexport function dotnetInitializeModule(internals: InternalExchange): void {\n    if (!Array.isArray(internals)) throw new Error(\"Expected internals to be an array\");\n    const runtimeApi = internals[InternalExchangeIndex.RuntimeAPI];\n    if (typeof runtimeApi !== \"object\") throw new Error(\"Expected internals to have RuntimeAPI\");\n\n    if (runtimeApi.runtimeBuildInfo.gitHash && runtimeApi.runtimeBuildInfo.gitHash !== GitHash) {\n        throw new Error(`Mismatched git hashes between loader and runtime. Loader: ${runtimeApi.runtimeBuildInfo.gitHash}, Runtime: ${GitHash}`);\n    }\n\n    const runtimeApiLocal: Partial<RuntimeAPI> = {\n        getAssemblyExports,\n        setModuleImports,\n    };\n    Object.assign(runtimeApi, runtimeApiLocal);\n    Object.assign(runtimeApi.INTERNAL, {\n        hasProperty,\n        getTypeOfProperty,\n        getProperty,\n        setProperty,\n        getGlobalThis,\n        getDotnetInstance,\n        dynamicImport,\n        bindCsFunction,\n        loadSatelliteAssemblies,\n        loadLazyAssembly,","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/index.ts#L18-L54","documentation":"The JSInterop Runtime module (System.Runtime.InteropServices.JavaScript.Native/interop) bakes a git hash at build time and compares it to the loader's runtimeBuildInfo.gitHash during dotnetInitializeModule(). A mismatch means the interop/runtime support JS was produced by a different build than the .NET runtime/loader and the interop ABI may not match.","triggerScenarios":"The interop bundle's consts:gitHash differs from the loader-reported hash; both are non-empty. Typically from mixing the interop JS of one workload version with the runtime of another.","commonSituations":"Stale cached interop JS vs. fresh runtime wasm; partial publish; dev rebuild that touched only the runtime project; CDN serving mixed-versions; using a nightly runtime with a release interop bundle.","solutions":["Deploy the complete _framework output from one build so the interop JS and runtime share a hash.","Clear all caches (browser, CDN, service worker) so no stale interop JS is served.","Clean and rebuild the solution (rm -rf bin obj) to guarantee a single stamped hash.","Confirm the workload/SDK version is consistent across all dotnet.* support files in wwwroot."],"exampleFix":"// before: nightly runtime + release interop JS\n\n// after\n// dotnet workload install wasm-tools --version <one consistent version>\n// dotnet publish -c Release\n// deploy the entire _framework together","handlingStrategy":"validation","validationCode":"import GitHash from \"consts:gitHash\";\n\nfunction assertInteropHashMatches(runtimeApi: any) {\n  const loader = runtimeApi?.runtimeBuildInfo?.gitHash;\n  if (loader && loader !== GitHash) {\n    throw new Error(`Interop build mismatch: loader=${loader}, interop=${GitHash}`);\n  }\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Deploy the entire _framework from one consistent publish.","Cache-bust interop JS assets to avoid stale bundles being served.","Clean and rebuild to guarantee a single stamped hash.","Keep one consistent workload/SDK version across all dotnet support files."],"tags":["git-hash","build-integrity","interop","version-mismatch"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}