{"record":{"id":"9b7de871c13c15b2","repo":"dotnet/runtime","slug":"method-instrumentation-is-not-enabled-please-enab-9b7de8","errorCode":null,"errorMessage":"method instrumentation is not enabled, please enable it with WasmPerformanceInstrumentation MSBuild property","messagePattern":"method instrumentation is not enabled, please enable it with WasmPerformanceInstrumentation MSBuild property","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/native/libs/System.Native.Browser/diagnostics/dotnet-cpu-profiler.ts","lineNumber":17,"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, commandSampleProfiler } from \"./client-commands\";\nimport { dotnetApi, dotnetLoaderExports, Module } from \"./cross-module\";\nimport { serverSession, setupJsClient } from \"./diagnostic-server-js\";\nimport { IDiagnosticSession } from \"./types\";\n\nexport function collectCpuSamples(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    if (!dotnetApi.getConfig().environmentVariables![\"DOTNET_WasmPerformanceInstrumentation\"]) {\n        throw new Error(\"method instrumentation is not enabled, please enable it with WasmPerformanceInstrumentation MSBuild property\");\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\n    setupJsClient({\n        onClosePromise: onClosePromise,\n        skipDownload: options.skipDownload,\n        commandOnAdvertise: () => commandSampleProfiler(options),\n        onSessionStart,\n    }, startup);\n    return onClosePromise.promise;","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/native/libs/System.Native.Browser/diagnostics/dotnet-cpu-profiler.ts#L1-L35","documentation":"collectCpuSamples() checks loaderConfig.environmentVariables['DOTNET_WasmPerformanceInstrumentation'] and throws if unset. Method instrumentation must be baked in at build time via the WasmPerformanceInstrumentation MSBuild property because the runtime needs to JIT-instrument method entry/exit probes. The env var is the runtime-side signal that the build produced an instrumented image.","triggerScenarios":"Calling collectCpuSamples() on a build published without <WasmPerformanceInstrumentation>true</WasmPerformanceInstrumentation>. Setting the env var manually without rebuilding (runtime checks both build and env). Publishing Release without the property.","commonSituations":"Trying to profile a production build that was published for size. Enabling DOTNET_WasmPerformanceInstrumentation in config but forgetting the MSBuild property. SDK upgrade resetting the property.","solutions":["Add <WasmPerformanceInstrumentation>true</WasmPerformanceInstrumentation> to the .csproj and republish.","Confirm both: the MSBuild property at build AND loaderConfig.environmentVariables.DOTNET_WasmPerformanceInstrumentation at runtime (the loader auto-sets it when the property is true).","If you cannot rebuild, use collectMetrics (counters) instead — they do not need instrumentation.","Verify the boot JSON contains the env var after publish."],"exampleFix":"// before: published normally\ncollectCpuSamples(); // throws\n\n// after: csproj\n<PropertyGroup>\n  <WasmPerformanceInstrumentation>true</WasmPerformanceInstrumentation>\n</PropertyGroup>\n// then dotnet publish, then collectCpuSamples works","handlingStrategy":"validation","validationCode":"function isInstrumentationEnabled(): boolean {\n  return !!dotnetApi.getConfig().environmentVariables?.['DOTNET_WasmPerformanceInstrumentation'];\n}\nif (!isInstrumentationEnabled()) {\n  console.error('Rebuild with <WasmPerformanceInstrumentation>true</WasmPerformanceInstrumentation>');\n}","typeGuard":"function isInstrumentedBuild(): boolean {\n  return !!dotnetApi.getConfig().environmentVariables?.['DOTNET_WasmPerformanceInstrumentation'];\n}","tryCatchPattern":"try { await collectCpuSamples(); } catch (e) {\n  if (/WasmPerformanceInstrumentation/.test((e as Error).message)) {\n    // tell user to rebuild with instrumentation, or fall back to counters\n    await collectMetrics();\n  } else throw e;\n}","preventionTips":["Set <WasmPerformanceInstrumentation>true</WasmPerformanceInstrumentation> in profiling builds only (it adds size).","Verify the env var appears in the published boot JSON before shipping a profiling build.","Fall back to collectMetrics() when instrumentation is unavailable.","Document in CI which build configurations enable instrumentation."],"tags":["diagnostics","profiler","msbuild","instrumentation"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}