{"record":{"id":"33927b221674321d","repo":"dotnet/runtime","slug":"no-active-js-diagnostic-session-33927b","errorCode":null,"errorMessage":"No active JS diagnostic session","messagePattern":"No active JS diagnostic session","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mono/browser/runtime/diagnostics/dotnet-gcdump.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 { commandStopTracing, commandGcHeapDump, } from \"./client-commands\";\nimport { IDiagnosticSession } from \"./common\";\nimport { loaderHelpers, Module } from \"./globals\";\nimport { serverSession, setupJsClient } from \"./diagnostics-js\";\n\nexport function collectGcDump (options?:DiagnosticCommandOptions):Promise<Uint8Array[]> {\n    if (!options) options = {};\n    if (!serverSession) {\n        throw new Error(\"No active JS diagnostic session\");\n    }\n\n    const onClosePromise = loaderHelpers.createPromiseController<Uint8Array[]>();\n    let stopDelayedAfterLastMessage = 0;\n    let stopSent = false;\n    function onData (session: IDiagnosticSession, message: Uint8Array): void {\n        session.store(message);\n        if (!stopSent) {\n            // stop 500ms after last GC message on this session, there will be more messages after that\n            if (stopDelayedAfterLastMessage) {\n                clearTimeout(stopDelayedAfterLastMessage);\n                Module.runtimeKeepalivePop();\n            }\n            stopDelayedAfterLastMessage = Module.safeSetTimeout(() => {\n                stopSent = true;\n                session.sendCommand(commandStopTracing(session.session_id));\n            }, 1000 * (options?.durationSeconds ?? 1));\n        }","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/mono/browser/runtime/diagnostics/dotnet-gcdump.ts#L1-L32","documentation":"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.","triggerScenarios":"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.","commonSituations":"Capturing a gcdump too early; runtime without diagnostics module; misconfigured diagnostic ports so no advert is produced.","solutions":["Wait for the runtime to be ready and `serverSession` to be established before calling `collectGcDump`.","Publish the runtime with diagnostics enabled.","Verify `DOTNET_DiagnosticPorts` is set so the runtime advertises."],"exampleFix":"// before: called before advert\nconst d = collectGcDump({}); // throws\n\n// after: wait for the session\nawait waitForDiagSession();\nconst d = collectGcDump({ durationSeconds: 2 });","handlingStrategy":"validation","validationCode":"function canCollectGcDump () {\n  return !!serverSession;\n}\nif (canCollectGcDump()) collectGcDump({ durationSeconds: 2 });","typeGuard":"function hasActiveDiagSession (): boolean {\n  return typeof serverSession !== 'undefined' && serverSession !== null;\n}","tryCatchPattern":null,"preventionTips":["Wait for the advert before triggering a gcdump.","Enable diagnostics in the runtime publish step.","Verify `DOTNET_DiagnosticPorts` is configured for the JS transport."],"tags":["diagnostics","gcdump","session-management","startup"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}