dotnet/aspnetcore · error · Error
The value ' ' is not a function.
Error message
The value '${identifier}' is not a function. What it means
Thrown by wrapJSCallAsFunction() in the FunctionCall case when the resolved member on the parent is not an instance of Function. .NET requested a function invocation (JSCallType.FunctionCall) but the named property is a value, getter returning non-function, or missing-as-value. The identifier in the message is the full dotted name.
Solutions
- Check whether the identifier is actually a function in the browser: typeof window.myObj.myValue === 'function'.
- Update the .NET Invoke identifier to the correct method name.
- If you meant to read a value, use JS.InvokeAsync<T> which uses GetValue semantics, not a function call.
Example fix
// before (C#)
await JS.InvokeVoidAsync("myObj.count"); // count is a number
// after
var count = await JS.InvokeAsync<int>("myObj.count"); // value read
// or call the real method
await JS.InvokeVoidAsync("myObj.increment"); Defensive patterns
Strategy: type-guard
Validate before calling
function isCallableMember(root, dotted) { const parts = dotted.split('.'); let c = root; for (let i = 0; i < parts.length - 1; i++) c = c?.[parts[i]]; return typeof c?.[parts[parts.length - 1]] === 'function'; } Type guard
function isFunctionMember(root: any, dotted: string): boolean { const parts = dotted.split('.'); let c = root; for (let i = 0; i < parts.length - 1; i++) c = c?.[parts[i]]; return typeof c?.[parts.at(-1)] === 'function'; } Try / catch
try { await JS.InvokeVoidAsync("myObj.doThing"); } catch (JSException e) when (e.Message.Contains("is not a function")) { /* verify typeof in console, fix identifier */ } Prevention
- Confirm typeof member === 'function' in the browser before wiring the .NET Invoke.
- Use value-read interop (InvokeAsync<T>) for properties, function-call interop for methods.
- Keep method names consistent across JS refactors and .NET call sites.
When it happens
Trigger: .NET calls JS.InvokeAsync('myObj.myValue') expecting a function, but myValue is a number/string/object. Distinct from a missing member (that throws in findObjectMember for intermediates, or isReadableProperty for GetValue); here the member exists but is not callable.
Common situations: Calling a property that holds data instead of a method (e.g. myObj.count vs myObj.getCount()); API renamed from method to property across versions; calling a constructor as a function or vice versa.
Related errors
- Could not find ' ' (' ' was undefined).
- The property ' ' is not defined or is not readable.
- The property ' ' is not writable.
- Byte array index ' ' does not exist.
- Cannot create a JSObjectReference from the value
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/47ba4c4bce82054f.
Report an issue: GitHub.
Appendix: source
Thrown at src/JSInterop/Microsoft.JSInterop.JS/src/src/Microsoft.JSInterop.ts:629
];
}
// Takes an object member and a call type and returns a function that performs the operation specified by the call type on the member.
//
// @param parent Immediate parent of the accessed object member.
// @param memberName Name (key) of the accessed member.
// @param callType The type of the operation to perform on the member.
// @param identifier The full member identifier. Only used for error messages.
// @returns A function that performs the operation on the member.
//
function wrapJSCallAsFunction(parent: any, memberName: string, callType: JSCallType, identifier: string): Function {
switch (callType) {
case JSCallType.FunctionCall:
const func = parent[memberName];
if (func instanceof Function) {
return func.bind(parent);
}
throw new Error(`The value '${identifier}' is not a function.`);
case JSCallType.ConstructorCall:
const ctor = parent[memberName];
if (ctor instanceof Function) {
const bound = ctor.bind(parent);
return (...args: any[]) => new bound(...args);
}
throw new Error(`The value '${identifier}' is not a function.`);
case JSCallType.GetValue:
if (!isReadableProperty(parent, memberName)) {
throw new Error(`The property '${identifier}' is not defined or is not readable.`);
}
return () => parent[memberName];
case JSCallType.SetValue:
if (!isWritableProperty(parent, memberName)) {
throw new Error(`The property '${identifier}' is not writable.`);
}View on GitHub (pinned to 3600ca084e)