dotnet/runtime · error · Error
${part} not found while looking up ${function_name}
Error message
${part} not found while looking up ${function_name} What it means
Thrown by mono_wasm_lookup_js_import when walking the dotted segments of a [JSImport]-annotated function name and an intermediate property is not present on the scope object. The runtime splits the function name on '.' and traverses each intermediate part; if any non-final segment is undefined, it throws before even checking whether the final name is callable.
Source
Thrown at src/mono/browser/runtime/invoke-js.ts:404
scope = importedModules.get(js_module_name);
if (WasmEnableThreads) {
mono_assert(scope, () => `ES6 module ${js_module_name} was not imported yet, please call JSHost.ImportAsync() on the UI or JSWebWorker thread first in order to invoke ${function_name}.`);
} else {
mono_assert(scope, () => `ES6 module ${js_module_name} was not imported yet, please call JSHost.ImportAsync() first in order to invoke ${function_name}.`);
}
} else if (parts[0] === "INTERNAL") {
scope = INTERNAL;
parts.shift();
} else if (parts[0] === "globalThis") {
scope = globalThis;
parts.shift();
}
for (let i = 0; i < parts.length - 1; i++) {
const part = parts[i];
const newscope = scope[part];
if (!newscope) {
throw new Error(`${part} not found while looking up ${function_name}`);
}
scope = newscope;
}
const fname = parts[parts.length - 1];
const fn = scope[fname];
if (typeof (fn) !== "function") {
throw new Error(`${function_name} must be a Function but was ${typeof fn}`);
}
// if the function was already bound to some object it would stay bound to original object. That's good.
return fn.bind(scope);
}
export function set_property (self: any, name: string, value: any): void {
mono_check(self, "Null reference");
self[name] = value;View on GitHub (pinned to 290d5ab72c)
Solutions
- Verify the JSImport attribute string exactly matches the export path in your JS module (check spelling and segment order).
- Ensure you awaited JSHost.ImportAsync(moduleName, url) for the module before invoking the import.
- Check the actual shape of the imported module (console.log the module object) to confirm the intermediate properties exist.
- Flatten the export or fix the attribute to match the real structure.
Example fix
// before: JS exports a flat function but JSImport uses a nested path
// JS: export function doThing() {}
// C#: [JSImport("myMod.Sub.doThing")] static partial void DoThing();
// after: match the real export shape
// C#: [JSImport("myMod.doThing")] static partial void DoThing();
// and import first: await JSHost.ImportAsync("myMod", "./myMod.js"); Defensive patterns
Strategy: validation
Validate before calling
// Verify each intermediate segment exists before binding [JSImport]
function pathResolvesToScope(scope, dotted) {
let s = scope;
for (const part of dotted.split('.').slice(0, -1)) {
if (s == null || !(part in s)) return false;
s = s[part];
}
return s != null;
}
if (!pathResolvesToScope(myModule, jsImportName)) { /* fix the path or import the module */ } Type guard
function isImportPathValid(scope: any, dotted: string): boolean {
let s = scope;
for (const part of dotted.split('.').slice(0, -1)) {
if (s == null || typeof s !== 'object' || !(part in s)) return false;
s = s[part];
}
return true;
} Prevention
- Always await JSHost.ImportAsync(moduleName, url) before invoking [JSImport]s in that module.
- Keep the JSImport attribute string in sync with the actual export path (use source-gen or tests).
- Write a smoke test that resolves all JSImport paths at startup.
When it happens
Trigger: Produced when binding a [JSImport] whose name contains intermediate path segments that do not exist on the resolved scope. E.g. [JSImport("Foo.Bar.Baz")] when the imported module/scope has Foo but no Foo.Bar property.
Common situations: Typo in the JSImport string; renamed/moved a JS export but did not update the attribute; the JS module was not imported via JSHost.ImportAsync before the [JSImport] binding ran; mismatch between the dotted path and the actual export shape (e.g. flat export referenced via nested path).
Related errors
- ${part} not found while looking up ${functionName}
- ${function_name} must be a Function but was ${typeof fn}
- ${functionName} must be a Function but was ${typeof fn}
- Cannot call synchronous C# methods.
- Cannot call synchronous C# method from inside a synchronous
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/9b7dcebd9d58a96f.
Report an issue: GitHub.