{"record":{"id":"b727cd6cde73b4c4","repo":"dotnet/runtime","slug":"runtime-is-not-running","errorCode":null,"errorMessage":"Runtime is not running","messagePattern":"Runtime is not running","errorType":"validation","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/290d5ab72cc1102813fbc0406fb186ceadabc340/src/native/libs/System.Native.Browser/diagnostics/diagnostic-server-js.ts#L132-L168","documentation":"Thrown by setupJsClient when called with startup=false while the .NET runtime is not yet running. Diagnostic clients (metrics, gcdump, cpu profiler) must attach either at startup (startup=true) or after the runtime is ready; attaching at runtime before readiness is invalid.","triggerScenarios":"Calling collectMetrics()/collectGcDump()/collectCpuSamples() (without startup=true) before dotnetLoaderExports.isRuntimeRunning() returns true.","commonSituations":"Invoking diagnostics from an onRuntimeInitialized callback that fires before the runtime reports running; an app-init race where the button handler runs too early.","solutions":["Wait for the runtime-ready signal before calling any runtime diagnostic collect function.","If you need data from the very start, register the client at startup with collect*(opts, true)."],"exampleFix":"// before: collecting metrics before runtime ready\nModule.onRuntimeInitialized = () => collectMetrics();\n// after: collect once the runtime reports running\nModule.onRuntimeInitialized = () =>\n  runtimeReady.then(() => collectMetrics());","handlingStrategy":"validation","validationCode":"// Only attach a runtime diagnostic client once the runtime is running\nif (!dotnetLoaderExports.isRuntimeRunning()) {\n  throw new Error('Runtime not ready; call collectMetrics after runtime-ready or use the startup hook.');\n}\ncollectMetrics();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Await the runtime-ready signal before calling any runtime diagnostic API.","Use the startup=true path for capture that must begin at boot.","Surface a clear app-state gate so UI cannot trigger diagnostics pre-ready."],"tags":["diagnostics","runtime-lifecycle","ordering"],"analyzedSha":"290d5ab72cc1102813fbc0406fb186ceadabc340","analyzedAt":"2026-08-06T19:57:01.276Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}