dotnet/aspnetcore · error

JS object instance with ID ${targetInstanceId} does not exis

Error message

JS object instance with ID ${targetInstanceId} does not exist (has it been disposed?).

What it means

Thrown by findJSFunction when cachedJSObjectsById[targetInstanceId] is undefined. Every JS object reference handed to .NET is cached by id; disposeJSObjectReferenceById (called when .NET disposes the JSObjectReference or a DotNetObject is GC'd) deletes that entry. A later call addressed to that id therefore cannot resolve the target.

Source

Thrown at src/JSInterop/Microsoft.JSInterop.JS/src/src/Microsoft.JSInterop.ts:578

      }
  }

  function formatError(error: Error | string): string {
      if (error instanceof Error) {
          return `${error.message}\n${error.stack}`;
      }

      return error ? error.toString() : "null";
  }

  export function findJSFunction(identifier: string, targetInstanceId: number, callType?: JSCallType): Function {
      const targetInstance = cachedJSObjectsById[targetInstanceId];

      if (targetInstance) {
          return targetInstance.resolveInvocationHandler(identifier, callType ?? JSCallType.FunctionCall);
      }

      throw new Error(`JS object instance with ID ${targetInstanceId} does not exist (has it been disposed?).`);
  }

  export function disposeJSObjectReferenceById(id: number) {
      delete cachedJSObjectsById[id];
  }

  /**
   * Traverses the object hierarchy to find an object member specified by the identifier.
   *
   * @param obj Root object to search in.
   * @param identifier Complete identifier of the member to find, e.g. "document.location.href".
   * @returns A tuple containing the immediate parent of the member and the member name.
   */
  export function findObjectMember(obj: any, identifier: string): [any, string] {
      const keys = identifier.split(".");
      let current = obj;

      // First, we iterate over all but the last key. We throw error for missing intermediate keys.

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Null-out and stop using the reference after disposal; set jsRef = null in the .NET dispose path.
  2. Capture a fresh reference each time the element/component mounts rather than reusing a stale one.
  3. Pin DotNetObject instances with DotNetObjectReference.Create and dispose explicitly; keep the .NET side alive for the call's lifetime.
  4. Guard the call: check the ref is valid before invoking.

Example fix

// before
@inject IJSRuntime JS
@code {
  private JSObjectReference _module;
  protected override async Task OnAfterRenderAsync(bool first) {
    if (first) _module = await JS.InvokeAsync<JSObjectReference>("import","./lib.js");
  }
  public void Dispose() { /* forgot to dispose _module */ }
  async Task Late() => await _module.InvokeVoidAsync("fn"); // stale id
}

// after
public async ValueTask DisposeAsync() {
  if (_module is not null) { await _module.DisposeAsync(); _module = null; }
}
Defensive patterns

Strategy: validation

Validate before calling

// .NET: track validity
private JSObjectReference _ref;
private bool _disposed;
async Task CallAsync() {
  if (_disposed || _ref is null) throw new ObjectDisposedException(nameof(_ref));
  await _ref.InvokeVoidAsync("fn");
}

Type guard

null

Try / catch

try {
  await jsRef.invokeMethodAsync('fn');
} catch (e) {
  if (/has it been disposed\?/i.test(e.message)) { jsRef = null; /* reacquire */ }
  else throw e;
}

Prevention

When it happens

Trigger: .NET holds a JSObjectReference or ElementReference whose id was already disposed; calling jsRef.invokeMethod after the ref was disposed; an element reference that survived a re-render where the element was removed; calling on a DotNetObject after dispose.

Common situations: Holding a JSObjectReference in a long-lived service after IJSRuntime.Dispose or component disposal; using ElementReference across a re-render where the element unmounted; memory-pressure-driven GC of a DotNetObject that was not pinned.

Related errors


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