{"record":{"id":"5d4703442ac1e2e4","repo":"dotnet/runtime","slug":"no-active-js-diagnostic-session-5d4703","errorCode":null,"errorMessage":"No active JS diagnostic session","messagePattern":"No active JS diagnostic session","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/native/libs/System.Native.Browser/diagnostics/dotnet-counters.ts","lineNumber":14,"sourceCode":"// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under the MIT license.\n\nimport type { DiagnosticCommandOptions } from \"../types\";\n\nimport { commandResumeRuntime, commandStopTracing, commandCounters } from \"./client-commands\";\nimport { dotnetLoaderExports, Module } from \"./cross-module\";\nimport { serverSession, setupJsClient } from \"./diagnostic-server-js\";\nimport { IDiagnosticSession } from \"./types\";\n\nexport function collectMetrics(options?: DiagnosticCommandOptions, startup?: boolean): Promise<Uint8Array[]> {\n    if (!options) options = {};\n    if (!startup && !serverSession) {\n        throw new Error(\"No active JS diagnostic session\");\n    }\n\n    const onClosePromise = dotnetLoaderExports.createPromiseCompletionSource<Uint8Array[]>();\n    function onSessionStart(session: IDiagnosticSession): void {\n        session.sendCommand(commandResumeRuntime());\n        // stop tracing after period of monitoring\n        Module.safeSetTimeout(() => {\n            session.sendCommand(commandStopTracing(session.sessionId));\n        }, 1000 * (options?.durationSeconds ?? 60));\n    }\n    setupJsClient({\n        onClosePromise: onClosePromise,\n        skipDownload: options.skipDownload,\n        commandOnAdvertise: () => commandCounters(options),\n        onSessionStart,\n    }, startup);\n    return onClosePromise.promise;\n}","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/native/libs/System.Native.Browser/diagnostics/dotnet-counters.ts#L1-L32","documentation":"collectMetrics() throws at its guard when called (startup=false) and serverSession is undefined. The diagnostic server inside the dotnet VM must have already advertised a session (setting serverSession) before counters can be collected. Same precondition as error 113 but checked locally in dotnet-counters.ts.","triggerScenarios":"Calling collectMetrics() before any advert arrived from the runtime. Calling it after the session closed and serverSession was cleared. Diagnostics module not loaded (jsModuleDiagnostics absent) so no session ever starts.","commonSituations":"Forgetting to enable diagnostics at build (diagnostics module not linked). Calling collectMetrics() too early in startup. Runtime exited before the call.","solutions":["Await dotnet.create() then verify the diagnostics JS module loaded (resources.jsModuleDiagnostics non-empty).","Pass startup=true to register the client at boot: collectMetrics({}, true) — this bypasses the serverSession check.","Set DOTNET_DiagnosticPorts=js://ready so the runtime opens a JS session.","Re-check after runtime exit; do not call collectors on a dead runtime."],"exampleFix":"// before\ncollectMetrics(); // serverSession undefined\n\n// after: register as startup client or wait\nconst runtime = await dotnet.create();\nawait collectMetrics(); // session exists after first advert","handlingStrategy":"validation","validationCode":"function canCollectMetrics(): boolean {\n  // serverSession exported from diagnostic-server-js\n  return !!serverSession;\n}","typeGuard":"function isSessionReady(): boolean { return !!serverSession; }","tryCatchPattern":"try { await collectMetrics(); } catch (e) {\n  if (/No active JS diagnostic session/.test((e as Error).message)) {\n    collectMetrics({}, true); // register at startup slot, then create runtime\n    await dotnet.create();\n  } else throw e;\n}","preventionTips":["Await dotnet.create() before calling collectMetrics().","Confirm jsModuleDiagnostics is present in the boot config (diagnostics module linked).","Use startup=true to register the client before runtime ready.","Gate collector UI behind a runtime-ready state."],"tags":["diagnostics","counters","session","lifecycle"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}