dotnet/aspnetcore · error
Method not found: ${method}
Error message
Method not found: ${method} What it means
Thrown by the web-worker handler after walking method.split('.').reduce(...) over workerExports and finding the result is not typeof 'function'. Either the dotted path does not resolve, or it resolves to a non-function (a namespace, an object, a constant). The reduce uses optional chaining so a missing segment yields undefined, which is also not a function.
Source
Thrown at src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWebWorker-CSharp/wwwroot/dotnet-web-worker.js:40
}
}
self.addEventListener('message', async (e) => {
if (e.data.type === 'init') {
await initialize(e.data.dotnetJsUrl, e.data.assemblyName);
return;
}
const { method, args, requestId } = e.data;
try {
if (Object.keys(workerExports).length === 0) {
throw new Error(startupError || "Worker .NET runtime not loaded");
}
const fn = method.split('.').reduce((obj, part) => obj?.[part], workerExports);
if (typeof fn !== 'function') {
throw new Error(`Method not found: ${method}`);
}
const result = await fn(...args);
self.postMessage({ type: "result", requestId, result }, collectTransferables(result));
} catch (err) {
self.postMessage({ type: "result", requestId, error: err?.message ?? String(err) });
}
});
function collectTransferables(value) {
if (ArrayBuffer.isView(value)) return [value.buffer];
if (value instanceof ArrayBuffer) return [value];
return [];
}
View on GitHub (pinned to 294cab2f9b)
Solutions
- Confirm the .NET method is annotated with [JSExport] (or the relevant export attribute) and the assembly is loaded.
- Log Object.keys(workerExports) after init to see what is actually exported.
- Match the dotted path exactly (namespace + type + method, correct casing).
- Ensure init's assemblyName argument matches the assembly that contains the export.
Example fix
// before
// C#: public class Ops { public static void Run() {} } // no [JSExport]
worker.postMessage({ method:'MyLib.Ops.Run', args:[], requestId:1 });
// after
// C#
[JSExport]
public static void Run() {}
// worker.postMessage({ method:'MyLib.Ops.Run', ... }) now resolves Defensive patterns
Strategy: type-guard
Validate before calling
function resolveMethod(exports, dotted) {
const fn = dotted.split('.').reduce((o,k)=>o?.[k], exports);
if (typeof fn !== 'function') throw new Error(`Method not found: ${dotted}`);
return fn;
} Type guard
function isExportedFunction(exports:any, dotted:string):boolean {
const fn = dotted.split('.').reduce((o:any,k:string)=>o?.[k], exports);
return typeof fn === 'function';
} Try / catch
try { worker.postMessage({method, args, requestId}); } catch (e) { if (/Method not found/.test(e.message)) { /* check [JSExport] */ } } Prevention
- Annotate exported .NET methods with [JSExport].
- Log Object.keys(workerExports) after init to verify availability.
- Keep caller method paths in sync with .NET renames.
When it happens
Trigger: Posting {method:'MyAssembly.Nonexistent'}; posting a namespace root like 'MyAssembly' (the exports object itself); a method name that was renamed or not exported with JSExportAttribute; casing mismatch in the dotted path; assemblyName mismatch in init so the expected export was never merged in.
Common situations: Forgetting [JSExport] on the .NET method; renaming a method without updating the caller; wrong assemblyName in init; using the static-method identifier format when only instance exports exist; namespace vs method confusion.
Related errors
- EqualTo validator requires a non-empty "other" parameter.
- FileExtensions validator requires a non-empty "extensions" p
- Range validator requires at least one of "min" or "max" para
- regex validator requires a non-empty "pattern" parameter.
- length/minlength/maxlength validator requires at least one o
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/fffba7245f606562.
Report an issue: GitHub.