dotnet/runtime · critical · Error
Expected internals to be an array
Error message
Expected internals to be an array
What it means
The System.Runtime.InteropServices.JavaScript interop module's dotnetInitializeModule asserts internals is an array. This module wires up JSImport/JSCall marshaling, lazy assembly loading, websockets, and HTTP, all of which read slots from the positional InternalExchange array, so a non-array breaks the contract before any interop can be set up.
Source
Thrown at src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/index.ts:31
} from "./invoke-js";
import { bindCsFunction, getAssemblyExports } from "./invoke-cs";
import { initializeMarshalersToJs, resolveOrRejectPromise } from "./marshal-to-js";
import { initializeMarshalersToCs } from "./marshal-to-cs";
import { forceDisposeProxies, releaseCSOwnedObject } from "./gc-handles";
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,View on GitHub (pinned to 290d5ab72c)
Solutions
- Forward the exact internals array produced by the runtime loader, unwrapped.
- Rebuild with a matching SDK so the loader and interop bundles agree on the InternalExchange array contract.
- Clear cached/stale bundles and redeploy all dotnet files together.
Example fix
// before
dotnetInitializeModule({ internals: arr })
// after
dotnetInitializeModule(arr) Defensive patterns
Strategy: type-guard
Validate before calling
if (!Array.isArray(internals)) throw new TypeError("internals must be an array");
dotnetInitializeModule(internals); Type guard
const isInternalExchange = (x): x is any[] => Array.isArray(x);
Prevention
- Forward the internals array from the runtime loader unwrapped.
- Rebuild loader and interop bundles together from one SDK.
When it happens
Trigger: dotnetInitializeModule for the interop module receives a non-array (object/undefined/null) because the host forwarded a wrapped or differently-shaped exchange instead of the raw array.
Common situations: Mismatched loader/interop bundle versions; a custom host wrapping internals in an object; partial deploy of dotnet bundles.
Related errors
- Expected internals to have RuntimeAPI
- Expected internals to be an array
- Expected internals to have RuntimeAPI
- Expected internals to be an array
- Expected internals to have RuntimeAPI
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/c786d8d97532a47d.
Report an issue: GitHub.