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

  1. Check whether the identifier is actually a function in the browser: typeof window.myObj.myValue === 'function'.
  2. Update the .NET Invoke identifier to the correct method name.
  3. 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

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


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)