{"record":{"id":"7bd170163b9efbc0","repo":"dotnet/runtime","slug":"expected-internals-to-have-runtimeapi-7bd170","errorCode":null,"errorMessage":"Expected internals to have RuntimeAPI","messagePattern":"Expected internals to have RuntimeAPI","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/native/libs/System.Native.Browser/native/index.ts","lineNumber":22,"sourceCode":"import type { InternalExchange, NativeBrowserExports, NativeBrowserExportsTable } from \"../types\";\nimport { InternalExchangeIndex } from \"../types\";\n\nimport { _ems_ } from \"../../Common/JavaScript/ems-ambient\";\nimport GitHash from \"consts:gitHash\";\n\nexport { SystemJS_RandomBytes } from \"./crypto\";\nexport { SystemJS_GetLocaleInfo } from \"./globalization-locale\";\nexport { SystemJS_RejectMainPromise, SystemJS_ResolveMainPromise, SystemJS_MarkAsyncMain, SystemJS_ConsoleClear } from \"./main\";\nexport { SystemJS_ScheduleTimer, SystemJS_ScheduleBackgroundJob, SystemJS_ScheduleFinalization, SystemJS_ScheduleDiagnosticServer } from \"./scheduling\";\nexport { ds_rt_websocket_close, ds_rt_websocket_create, ds_rt_websocket_poll, ds_rt_websocket_recv, ds_rt_websocket_send, ds_rt_browser_performance_measure } from \"./diagnostics\";\n\n\nexport const gitHash = GitHash;\nexport function dotnetInitializeModule(internals: InternalExchange): void {\n    if (!Array.isArray(internals)) throw new Error(\"Expected internals to be an array\");\n\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 !== _ems_.DOTNET.gitHash) {\n        throw new Error(`Mismatched git hashes between loader and runtime. Loader: ${runtimeApi.runtimeBuildInfo.gitHash}, DOTNET: ${_ems_.DOTNET.gitHash}`);\n    }\n\n    internals[InternalExchangeIndex.NativeBrowserExportsTable] = nativeBrowserExportsToTable({\n        getWasmMemory,\n        getWasmTable,\n        SystemJS_ScheduleDiagnosticServer: _ems_._SystemJS_ScheduleDiagnosticServer,\n        SystemJS_GetMethodName: (pMethodDesc: number) => _ems_._SystemJS_GetMethodName(pMethodDesc),\n    });\n    _ems_.dotnetUpdateInternals(internals, _ems_.dotnetUpdateInternalsSubscriber);\n\n    setupEmscripten();\n\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    function nativeBrowserExportsToTable(map: NativeBrowserExports): NativeBrowserExportsTable {\n        // keep in sync with nativeBrowserExportsFromTable()","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/dotnet/runtime/blob/290d5ab72cc1102813fbc0406fb186ceadabc340/src/native/libs/System.Native.Browser/native/index.ts#L4-L40","documentation":"After the array check, the native module reads internals[InternalExchangeIndex.RuntimeAPI] and asserts it is an object. Without the runtime API handle it cannot register the NativeBrowserExportsTable, install Emscripten hooks, or call dotnetUpdateInternals, so initialization is aborted.","triggerScenarios":"internals is a valid array but the RuntimeAPI slot is undefined — wrong array length, the slot not yet populated by the core runtime, or reordered indices caused by a loader/native version mismatch.","commonSituations":"Native bundle initialized before the core runtime populated RuntimeAPI; a version mismatch that shifts InternalExchangeIndex values; a partial deploy where only some bundles updated.","solutions":["Load the core dotnet runtime bundle (which populates internals[InternalExchangeIndex.RuntimeAPI]) before initializing the native browser module.","Rebuild/republish all dotnet artifacts from one SDK/commit so InternalExchangeIndex values line up.","Purge CDN/browser/service-worker caches of mixed-version bundles."],"exampleFix":"// before: init called before runtime populated the slot\n// internals[0] === undefined\ndotnetInitializeModule(internals);\n\n// after: ensure runtime API is present\nif (typeof internals[0] !== \"object\") throw new Error(\"load runtime first\");\ndotnetInitializeModule(internals);","handlingStrategy":"type-guard","validationCode":"if (!Array.isArray(internals) || typeof internals[0] !== \"object\")\n  throw new Error(\"RuntimeAPI missing — load core runtime first\");\ndotnetInitializeModule(internals);","typeGuard":"const hasRuntimeApi = (x: any[]): x is any[] =>\n  Array.isArray(x) && typeof x[0] === \"object\" && x[0] !== null;","tryCatchPattern":null,"preventionTips":["Initialize the native browser module only after the core runtime has populated internals[0].","Keep loader and native bundles from the same build so InternalExchangeIndex values agree."],"tags":["initialization","runtime-interop","internals"],"analyzedSha":"290d5ab72cc1102813fbc0406fb186ceadabc340","analyzedAt":"2026-08-06T19:57:01.276Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}