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

  1. Confirm the .NET method is annotated with [JSExport] (or the relevant export attribute) and the assembly is loaded.
  2. Log Object.keys(workerExports) after init to see what is actually exported.
  3. Match the dotted path exactly (namespace + type + method, correct casing).
  4. 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

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


AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06). Data as JSON: /api/errors/fffba7245f606562. Report an issue: GitHub.