dotnet/runtime · error · Error

No active session to reconnect

Error message

No active session to reconnect

What it means

connectDSRouter() requires an existing JS diagnostic session to take over — it closes the JS-side wrapper for serverSession.clientSocket and re-opens it as a WebSocket toward a dotnet-dsrouter. Without serverSession there is no socket to migrate, so the call is meaningless and throws.

Solutions

  1. Trigger a diagnostic session first (e.g. collectMetrics({}, true) at startup) so serverSession is populated.
  2. Ensure initializeDS() ran, which sets DOTNET_DiagnosticPorts=js://ready in web environments so the runtime opens the JS socket.
  3. Await Module.onDotnetReady and a first advert before calling connectDSRouter.
  4. If you do not need JS sessions, do not call connectDSRouter — let the runtime open the WebSocket directly via its diagnostic port env var.

Example fix

// before
connectDSRouter('ws://localhost:8181'); // serverSession undefined

// after: seed a session at startup
const dotnetDiagnosticClient = (scenario) => ({ /* IDiagnosticClient */ });
collectMetrics({}, true); // populates serverSession
await dotnet.create();
connectDSRouter('ws://localhost:8181');
Defensive patterns

Strategy: validation

Validate before calling

function hasServerSession(): boolean {
  // serverSession is exported from diagnostic-server-js
  // import { serverSession } from './diagnostic-server-js';
  return !!serverSession;
}
if (hasServerSession()) connectDSRouter(wsUrl);

Type guard

function isSessionActive(s: unknown): s is { clientSocket: number } {
  return !!s && typeof s === 'object' && typeof (s as any).clientSocket === 'number';
}

Try / catch

try { connectDSRouter(url); } catch (e) {
  if (/No active session/.test((e as Error).message)) {
    await waitForFirstAdvert();
    connectDSRouter(url);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling connectDSRouter(wsUrl) before any JS diagnostic session has been established (i.e. before serverSession was set by an advert message from the runtime). Calling it after the session already closed. Calling it in an environment where diagnostics were never enabled (DOTNET_DiagnosticPorts not set).

Common situations: Wiring up dotnet-dsrouter before triggering any diagnostic collection. Forgetting to enable DOTNET_DiagnosticPorts=js://ready via initializeDS. Calling connectDSRouter at app start instead of after the first session.

Related errors


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

Appendix: source

Thrown at src/native/libs/System.Native.Browser/diagnostics/diagnostic-server.ts:78

    }
    const bufferPtr: VoidPtr = buffer as any >>> 0 as any;
    return wrapper.recv(bufferPtr, bytesToRead);
}

export function ds_rt_websocket_close(clientSocket: number): number {
    const wrapper = socketHandles.get(clientSocket);
    if (!wrapper) {
        return -1;
    }
    socketHandles.delete(clientSocket);
    return wrapper.close();
}

// this will take over the existing connection to JS and send new advert message to WS client
// use dotnet-dsrouter server-websocket -v trace
export function connectDSRouter(url: string): void {
    if (!serverSession) {
        throw new Error("No active session to reconnect");
    }

    // make sure new sessions hit the new URL
    urlOverride = url;

    const oldWrapper = socketHandles.get(serverSession.clientSocket);
    if (oldWrapper) {
        oldWrapper.close();
    }
    const wrapper = createDiagConnectionWs(serverSession.clientSocket, url);
    socketHandles.set(serverSession.clientSocket, wrapper);
    wrapper.send(advertise());
}

export function initializeDS() {
    const loaderConfig = dotnetApi.getConfig();
    const diagnosticPorts = "DOTNET_DiagnosticPorts";
    loaderConfig.environmentVariables ??= {};

View on GitHub (pinned to 60108ba66e)