dotnet/BenchmarkDotNet · error · InvalidOperationException

TotalOperations is missing, unable to calculate stats

Error message

TotalOperations is missing, unable to calculate stats

What it means

CalculateMetrics throws when totalOperationsPerIteration was never set, i.e. the trace contained no Workload iteration events at all. Without the per-iteration operations count the diagnoser cannot convert raw PMC samples into per-operation metrics.

Source

Thrown at src/BenchmarkDotNet.Diagnostics.Windows/Tracing/TraceLogParser.cs:128

                    totalOperationsPerIteration = totalOperations;
                else if (totalOperationsPerIteration.Value != totalOperations)
                    throw new InvalidOperationException($"TotalOperations count can't change during the benchmark run! Invalid trace!");

                workloadTimestamps.Add(timeStamp);
            }
        }

        public void HandleNewSample(double timeStamp, ulong instructionPointer, int profileSourceId)
            => samples.Add((timeStamp, instructionPointer, profileSourceId));

        public IEnumerable<Metric> CalculateMetrics(Dictionary<int, int> profileSourceIdToInterval, PreciseMachineCounter[] counters)
        {
            if (overheadTimestamps.Count % 2 != 0)
                throw new InvalidOperationException("One overhead iteration stop event is missing, unable to calculate stats");
            if (workloadTimestamps.Count % 2 != 0)
                throw new InvalidOperationException("One workload iteration stop event is missing, unable to calculate stats");
            if (!totalOperationsPerIteration.HasValue)
                throw new InvalidOperationException("TotalOperations is missing, unable to calculate stats");

            var overheadIterations = CreateIterationData(overheadTimestamps);
            var workloadIterations = CreateIterationData(workloadTimestamps);

            SumCountersPerIterations(profileSourceIdToInterval, workloadIterations, overheadIterations, counters);

            var workloadTotalPerCounter = Sum(workloadIterations);
            var overheadTotalPerCounter = Sum(overheadIterations);

            return workloadTotalPerCounter.Select(perCounter =>
            {
                var pmc = counters.Single(counter => counter.ProfileSourceId == perCounter.Key);

                overheadTotalPerCounter.TryGetValue(perCounter.Key, out var overhead);

                // result = (avg(workload) - avg(overhead))/op
                double result = perCounter.Value / (double)workloadIterations.Length;

View on GitHub (pinned to b515068b61)

Solutions

  1. Confirm the .etl actually contains the benchmark workload phase for the target process.
  2. Ensure the benchmark is not filtered out and actually runs.
  3. Capture the trace covering the full benchmark run window, not just setup/overhead.
Defensive patterns

Strategy: validation

Try / catch

try { /* parse trace */ }
catch (InvalidOperationException ex) when (ex.Message.Contains("TotalOperations is missing"))
{
    log.Error("Trace has no workload iteration events; capture covered the wrong process/window.");
}

Prevention

When it happens

Trigger: ProcessMetrics received no Workload-mode iteration events before CalculateMetrics ran. Typically means the benchmarked process never emitted Benchmarking ETW events (wrong process attributed), or the trace was captured before/after the workload phase.

Common situations: Running the PMC diagnoser against a process that is not the benchmark host; attaching the ETW session to the wrong PID; capturing an empty/partial .etl; the [Benchmark] was filtered out and never executed.

Related errors


AI-assisted analysis of dotnet/BenchmarkDotNet@b515068b61 (2026-08-13). Data as JSON: /api/errors/ba2c5c5dadf07a53. Report an issue: GitHub.