{"record":{"id":"b727cd6cde73b4c4","repo":"dotnet/runtime","slug":"runtime-is-not-running","errorCode":null,"errorMessage":"Runtime is not running","messagePattern":"Runtime is not running","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/native/libs/System.Native.Browser/diagnostics/diagnostic-server-js.ts","lineNumber":150,"sourceCode":"        if (this.messagesToSend.length === 0) {\n            return 0;\n        }\n        if (this.diagClient && !this.diagClient.skipDownload) {\n            downloadBlob(this.messagesToSend);\n        }\n        this.messagesToSend = [];\n        return 0;\n    }\n}\n\nexport function initializeJsClient() {\n    nextJsClient = dotnetLoaderExports.createPromiseCompletionSource<IDiagnosticClient>();\n    startupJsClient = undefined;\n}\n\nexport function setupJsClient(client: IDiagnosticClient, startup?: boolean) {\n    if (!startup && !dotnetLoaderExports.isRuntimeRunning()) {\n        throw new Error(\"Runtime is not running\");\n    }\n    if (startup) {\n        if (startupJsClient) {\n            throw new Error(\"startup diagnostic client already registered\");\n        }\n        startupJsClient = client;\n    } else {\n        if (nextJsClient.isDone) {\n            throw new Error(\"multiple clients in parallel are not allowed\");\n        }\n        nextJsClient.resolve(client);\n    }\n}\n\nexport function createDiagConnectionJs(socketHandle: number, scenarioName: string): DiagnosticSession {\n    if (!fromScenarioNameOnce) {\n        fromScenarioNameOnce = true;\n        if (scenarioName.startsWith(\"js://gcdump\")) {","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/native/libs/System.Native.Browser/diagnostics/diagnostic-server-js.ts#L132-L168","documentation":"setupJsClient() with startup=false calls dotnetLoaderExports.isRuntimeRunning() and throws if it returns false. Diagnostic clients that are not 'startup' clients can only attach to a live runtime, because they need an active diagnostic server inside the dotnet VM to accept their connection.","triggerScenarios":"Calling collectMetrics()/collectCpuSamples()/collectGcDump() (which call setupJsClient with startup=false) before the runtime finished initializing. Calling setupJsClient(client) directly in onConfigLoaded or module initializer before the native module is ready.","commonSituations":"Invoking diagnostic collectors from a JS module initializer that runs during boot (before runtime ready). Race between await dotnet.create() and a side-effect that registers a diagnostic client. Trying to attach a collector to a runtime that exited.","solutions":["Await dotnet.create() (or Module.onDotnetReady) before calling collectMetrics/collectCpuSamples/collectGcDump.","If you must register before runtime ready, pass startup=true to use the startupJsClient slot.","Guard with isRuntimeRunning() yourself and queue the call for onDotnetReady.","Check runtimeState.dotnetReady if you have internals access."],"exampleFix":"// before: collector called too early\ncollectMetrics();\n\n// after\nconst runtime = await dotnet.create();\ncollectMetrics();","handlingStrategy":"validation","validationCode":"function runtimeIsRunning(): boolean {\n  // exposed by the loader; equivalent to dotnetLoaderExports.isRuntimeRunning()\n  return typeof (globalThis as any).dotnet?.getConfig === 'function' && !!(globalThis as any).dotnet?.runtime?.runtimeId;\n}","typeGuard":"function isRuntimeReady(): boolean {\n  // Use the loader-exported helper if available\n  return (globalThis as any).__dotnetRuntimeReady === true;\n}","tryCatchPattern":"try { collectMetrics(); } catch (e) {\n  if (/Runtime is not running/.test((e as Error).message)) {\n    await dotnet.create();\n    collectMetrics();\n  } else throw e;\n}","preventionTips":["Always await dotnet.create() before invoking diagnostic collectors.","Use Module.onDotnetReady callback to gate diagnostic UI.","For startup-time collection, pass startup=true instead of waiting.","Guard collector calls behind a runtime-ready flag in your state."],"tags":["diagnostics","lifecycle","runtime"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}