dotnet/runtime · error · Error

No active JS diagnostic session

Error message

No active JS diagnostic session

What it means

Thrown by `collectGcDump` (dotnet-gcdump) when there is no active JS diagnostic session. Like the other collectors, it depends on `serverSession` to send the GC heap dump command; calling it before the runtime advertised a session is rejected.

Solutions

  1. Wait for the runtime to be ready and `serverSession` to be established before calling `collectGcDump`.
  2. Publish the runtime with diagnostics enabled.
  3. Verify `DOTNET_DiagnosticPorts` is set so the runtime advertises.

Example fix

// before: called before advert
const d = collectGcDump({}); // throws

// after: wait for the session
await waitForDiagSession();
const d = collectGcDump({ durationSeconds: 2 });
Defensive patterns

Strategy: validation

Validate before calling

function canCollectGcDump () {
  return !!serverSession;
}
if (canCollectGcDump()) collectGcDump({ durationSeconds: 2 });

Type guard

function hasActiveDiagSession (): boolean {
  return typeof serverSession !== 'undefined' && serverSession !== null;
}

Prevention

When it happens

Trigger: Calling `collectGcDump(options)` (dotnet-gcdump.ts:11) before `serverSession` is set in diagnostics-js.ts. Happens at startup, when diagnostics is disabled in the runtime, or before the advert arrives.

Common situations: Capturing a gcdump too early; runtime without diagnostics module; misconfigured diagnostic ports so no advert is produced.

Related errors


AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10). Data as JSON: /api/errors/33927b221674321d. Report an issue: GitHub.

Appendix: source

Thrown at src/mono/browser/runtime/diagnostics/dotnet-gcdump.ts:14

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import type { DiagnosticCommandOptions } from "../types";

import { commandStopTracing, commandGcHeapDump, } from "./client-commands";
import { IDiagnosticSession } from "./common";
import { loaderHelpers, Module } from "./globals";
import { serverSession, setupJsClient } from "./diagnostics-js";

export function collectGcDump (options?:DiagnosticCommandOptions):Promise<Uint8Array[]> {
    if (!options) options = {};
    if (!serverSession) {
        throw new Error("No active JS diagnostic session");
    }

    const onClosePromise = loaderHelpers.createPromiseController<Uint8Array[]>();
    let stopDelayedAfterLastMessage = 0;
    let stopSent = false;
    function onData (session: IDiagnosticSession, message: Uint8Array): void {
        session.store(message);
        if (!stopSent) {
            // stop 500ms after last GC message on this session, there will be more messages after that
            if (stopDelayedAfterLastMessage) {
                clearTimeout(stopDelayedAfterLastMessage);
                Module.runtimeKeepalivePop();
            }
            stopDelayedAfterLastMessage = Module.safeSetTimeout(() => {
                stopSent = true;
                session.sendCommand(commandStopTracing(session.session_id));
            }, 1000 * (options?.durationSeconds ?? 1));
        }

View on GitHub (pinned to 60108ba66e)