dotnet/BenchmarkDotNet · error · InvalidOperationException
One workload iteration stop event is missing, unable to calc
Error message
One workload iteration stop event is missing, unable to calculate stats
What it means
Symmetric to the overhead check: CalculateMetrics throws when workloadTimestamps.Count is odd, i.e. a WorkloadActualStart had no matching WorkloadActualStop. Without complete workload iteration boundaries the PMC counter samples cannot be attributed to iterations.
Source
Thrown at src/BenchmarkDotNet.Diagnostics.Windows/Tracing/TraceLogParser.cs:126
{
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);
// result = (avg(workload) - avg(overhead))/opView on GitHub (pinned to b515068b61)
Solutions
- Make sure the benchmark method does not throw so the engine can emit the stop event.
- Raise ETW buffer size and number of buffers when collecting the .etl.
- Re-run in isolation; intermittent event loss is environment-dependent.
Defensive patterns
Strategy: retry
Try / catch
try { /* run + parse trace */ }
catch (InvalidOperationException ex) when (ex.Message.Contains("workload iteration stop event is missing"))
{
log.Warning("ETW dropped a workload stop event; rerun with larger buffers / in isolation.");
} Prevention
- Make the benchmark method not throw so the engine emits WorkloadActualStop.
- Raise ETW buffer size/count on noisy machines.
- Capture the full run window; avoid partial traces.
When it happens
Trigger: An ETW WorkloadActualStop event is missing from the trace. Same root causes as the overhead variant: dropped events, process exit mid-iteration, partial capture, or an exception that aborted the workload before the stop event fired.
Common situations: Benchmark threw an unhandled exception inside a workload iteration; ETW buffer overflow on a noisy machine; the trace was started/stopped asynchronously and missed the final stop event.
Related errors
- One overhead iteration stop event is missing, unable to calc
- TotalOperations is missing, unable to calculate stats
- Sampling interval change is not supported!
- TotalOperations count can't change during the benchmark run!
- Please use Targets property
AI-assisted analysis of dotnet/BenchmarkDotNet@b515068b61 (2026-08-13).
Data as JSON: /api/errors/51db5d98bea861e8.
Report an issue: GitHub.