dotnet/runtime · error · Error
Failed to invoke 'onRuntimeReady' on library initializer
Error message
Failed to invoke 'onRuntimeReady' on library initializer '${name}': ${message} What it means
Thrown by callLibraryInitializerOnRuntimeReady() (src/native/libs/Common/JavaScript/loader/assets.ts:86). After the runtime is ready, the loader invokes each module's onRuntimeReady(dotnetApi) hook; if the hook throws or rejects, the catch at line 93 wraps the original error and re-throws, tagging it with the initializer's name.
Solutions
- Read error.cause to find the underlying failure in the named initializer and fix it.
- Test the initializer against the exact runtime version it will run under.
- Register all JS exports the initializer needs before onRuntimeReady runs.
Example fix
// before: initializer calls an API that does not exist yet
export function onRuntimeReady(api) {
api.setHeapLock(true); // TypeError -> 'Failed to invoke onRuntimeReady'
}
// after
export function onRuntimeReady(api) {
if (typeof api.setHeapLock === 'function') api.setHeapLock(true);
} Defensive patterns
Strategy: try-catch
Validate before calling
async function safeReadyHook(mod: any, api: any): Promise<void> {
if (typeof mod?.onRuntimeReady === 'function') {
await mod.onRuntimeReady(api);
}
} Type guard
function hasOnRuntimeReady(m: any): m is { onRuntimeReady: (api: any) => void | Promise<void> } {
return typeof m?.onRuntimeReady === 'function';
} Try / catch
try {
await callLibraryInitializerOnRuntimeReady([asset, modulePromise]);
} catch (err) {
// err.cause is the underlying initializer error
console.error('onRuntimeReady failed:', (err as Error).message, (err as any).cause);
throw err;
} Prevention
- Register all JS exports an initializer needs before onRuntimeReady runs.
- Feature-detect dotnetApi methods before calling them in the initializer.
- Test the initializer against the runtime version it will ship with.
When it happens
Trigger: A module listed in resources.modulesAfterRuntimeReady exports onRuntimeReady; the loader calls it with the runtime API; if it throws synchronously or returns a rejected promise, the error is wrapped and rethrown.
Common situations: A library initializer that uses dotnetApi incorrectly against the deployed runtime version; an initializer that fails to register a JS export the managed side expects; a bug in the onRuntimeReady body; a missing dependency the initializer needs at runtime-ready time.
Related errors
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/e6bc42d1f4a35812.
Report an issue: GitHub.
Appendix: source
Thrown at src/native/libs/Common/JavaScript/loader/assets.ts:95
await module.onRuntimeConfigLoaded(loaderConfig);
}
return module;
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
throw new Error(`Failed to invoke 'onRuntimeConfigLoaded' on library initializer '${name}': ${message}`, { cause: err });
}
}
export async function callLibraryInitializerOnRuntimeReady([asset, modulePromise]: [JsAsset, Promise<any>]): Promise<void> {
const module = await modulePromise;
const name = asset.name || asset.resolvedUrl || "unknown";
try {
if (typeof module.onRuntimeReady === "function") {
await module.onRuntimeReady(dotnetApi);
}
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
throw new Error(`Failed to invoke 'onRuntimeReady' on library initializer '${name}': ${message}`, { cause: err });
}
}
export function fetchMainWasm(asset: WasmAsset): Promise<Response> {
totalAssetsToDownload++;
const assetInternal = asset as AssetEntryInternal;
if (assetInternal.name && !asset.resolvedUrl) {
asset.resolvedUrl = locateFile(assetInternal.name);
}
assetInternal.behavior = "dotnetwasm";
if (!asset.resolvedUrl) throw new Error("Invalid config, resources is not set");
mainWasmAsset = asset;
wasmBinaryPromise = loadResource(assetInternal);
return wasmBinaryPromise;
}
export async function instantiateMainWasm(imports: WebAssembly.Imports, successCallback: InstantiateWasmSuccessCallback): Promise<void> {
const assetInternal = mainWasmAsset as AssetEntryInternal;View on GitHub (pinned to 60108ba66e)