dotnet/runtime · critical · Error
Expected internals to have RuntimeAPI
Error message
Expected internals to have RuntimeAPI
What it means
Thrown by the external post-message loader module's dotnetInitializeModule when internals[0] (the RuntimeAPI exchange slot, index InternalExchangeIndex.RuntimeAPI) is not an object. This slot carries the runtime handle the loader needs to call createDotnetRuntime, so without it initialization cannot proceed. The extpost module is the worker/iframe variant that bridges runtime APIs across a postMessage boundary.
Source
Thrown at src/native/libs/System.Native.Browser/libSystem.Native.Browser.extpost.js:14
//
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
/* eslint-disable no-undef */
/* eslint-disable @typescript-eslint/no-unused-vars */
var fetch = fetch || undefined; var dotnetNativeModuleLoaded = false; var dotnetInternals = null;
export function dotnetInitializeModule(internals) {
if (dotnetNativeModuleLoaded) throw new Error("Native module already loaded");
dotnetNativeModuleLoaded = true;
if (!Array.isArray(internals)) throw new Error("Expected internals to be an array");
dotnetInternals = internals;
const runtimeApi = internals[0/*InternalExchangeIndex.RuntimeAPI*/];
if (typeof runtimeApi !== "object") throw new Error("Expected internals to have RuntimeAPI");
if (typeof runtimeApi.Module !== "object") throw new Error("Expected internals to have Module");
return createDotnetRuntime(runtimeApi.Module);
}
View on GitHub (pinned to 290d5ab72c)
Solutions
- Ensure the core dotnet runtime bundle loads and populates internals[InternalExchangeIndex.RuntimeAPI] before the extpost module's dotnetInitializeModule runs.
- Rebuild/republish the app with a single matching .NET runtime SDK so the loader, extpost, and runtime share the same InternalExchange layout and indices.
- Clear browser cache / CDN / service-worker cache of stale dotnet.*.js artifacts and redeploy.
Example fix
// before dotnetInitializeModule([]) // RuntimeAPI slot missing // after dotnetInitializeModule([runtimeApi /* index 0 = RuntimeAPI */, /* other slots */])
Defensive patterns
Strategy: type-guard
Validate before calling
function assertInternals(internals) {
if (!Array.isArray(internals)) throw new Error("internals is not an array");
if (typeof internals[0] !== "object" || internals[0] === null)
throw new Error("internals[0] (RuntimeAPI) is not an object");
}
assertInternals(internals); Type guard
const isInternalExchange = (x): x is any[] => Array.isArray(x) && typeof x[0] === "object" && x[0] !== null;
Prevention
- Always load dotnet.* bundles from the same build output; never mix SDK versions.
- In custom loaders, verify internals length and the RuntimeAPI slot before forwarding to dotnetInitializeModule.
When it happens
Trigger: Calling dotnetInitializeModule(internals) where internals[0] is undefined, null, or a primitive — the RuntimeAPI was never populated, the array is too short, or slots were constructed in the wrong order before the extpost bundle initialized.
Common situations: A custom worker/loader that rebuilds the internals array on the receiving side of a postMessage and misorders/omits the RuntimeAPI slot; the core runtime bundle failed to load earlier so RuntimeAPI stays undefined; mixing a newer extpost bundle with an older runtime that uses a different InternalExchange layout.
Related errors
- Expected internals to be an array
- Expected internals to have RuntimeAPI
- Expected internals to be an array
- Expected internals to have RuntimeAPI
- Expected internals to be an array
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/6a9cbafabd86b75e.
Report an issue: GitHub.