dotnet/BenchmarkDotNet · error · InvalidOperationException

One overhead iteration stop event is missing, unable to calc

Error message

One overhead iteration stop event is missing, unable to calculate stats

What it means

CalculateMetrics requires overhead (jitting/allocations floor) iterations to come in start/stop pairs. It throws when overheadTimestamps.Count is odd, meaning an OverheadActualStart was seen without its matching OverheadActualStop, so an iteration boundary cannot be reconstructed.

Source

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

            }
            else if (iterationMode == IterationMode.Workload)
            {
                if (!totalOperationsPerIteration.HasValue)
                    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);

View on GitHub (pinned to b515068b61)

Solutions

  1. Increase ETW session buffer sizes / use a real-time session with larger buffers to avoid dropped events.
  2. Ensure the benchmark run completes without exceptions so all Start/Stop pairs are emitted.
  3. Re-run the benchmark; transient event loss often does not recur.
Defensive patterns

Strategy: retry

Try / catch

try { /* run + parse trace */ }
catch (InvalidOperationException ex) when (ex.Message.Contains("overhead iteration stop event is missing"))
{
    log.Warning("ETW dropped an overhead stop event; increasing buffers and rerunning.");
    // increase ETW buffer sizes and rerun
}

Prevention

When it happens

Trigger: The ETW trace is missing an OverheadActualStop (or Start) event. Caused by event loss in the ETW session, the benchmarked process crashing/exiting mid-iteration, or the trace being captured over only part of the run.

Common situations: Capturing an .etl with insufficient buffer size (events dropped); the process under test was killed; trace started after the first overhead iteration or stopped before the last; running the PMC diagnoser on a benchmark that threw an exception partway through.

Related errors


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