{"record":{"id":"b91b2d9882d1736b","repo":"JuliusBrussee/caveman","slug":"cachebench-replay-schedule-interrupted-w","errorCode":null,"errorMessage":"cachebench: replay schedule interrupted: %w","messagePattern":"cachebench: replay schedule interrupted: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cacheengine/cachebench/replay.go","lineNumber":565,"sourceCode":"\t\t}\n\t}\n\tfor provider := range providers {\n\t\tif eligible[provider] < target.MinEligibleRequest {\n\t\t\treturn fmt.Errorf(\"cachebench: provider %q engine-eligible population %d cannot meet minimum %d\", provider, eligible[provider], target.MinEligibleRequest)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (runner ReplayRunner) runSequential(ctx context.Context, prepared []preparedReplay, anchorTrace, anchorReal time.Time, now func() time.Time, sleep func(context.Context, time.Duration) error, emit func(ReplayResult) error) error {\n\tfor _, item := range prepared {\n\t\trecord := item.record\n\t\ttraceAt, _ := time.Parse(time.RFC3339Nano, record.At)\n\t\toffset, _ := scaledReplayGap(traceAt.Sub(anchorTrace), runner.TimeScale)\n\t\tscheduled := anchorReal.Add(offset)\n\t\tif delay := scheduled.Sub(now().UTC()); delay > 0 {\n\t\t\tif err := sleep(ctx, delay); err != nil {\n\t\t\t\treturn fmt.Errorf(\"cachebench: replay schedule interrupted: %w\", err)\n\t\t\t}\n\t\t}\n\t\tstarted := now().UTC()\n\t\tevidence := replayEvidenceBase(record, item.optimized, runner.TimeScale, scheduled, started, runner.Limits.MaxScheduleDrift)\n\t\tif runner.Limits.RequireGroundedTiming && evidence.ScheduleDriftMilliseconds > evidence.ScheduleToleranceMilliseconds {\n\t\t\tevidence.FailureCode = \"schedule_drift\"\n\t\t\tevidence.CompletedAt = now().UTC().Format(time.RFC3339Nano)\n\t\t\tif err := emitValidatedReplayResult(emit, ReplayResult{Evidence: evidence}); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\treturn &ReplayRunError{\n\t\t\t\tRequestID: record.RequestID, FailureCode: evidence.FailureCode,\n\t\t\t\tErr: fmt.Errorf(\"cachebench: request %q exceeded schedule drift tolerance\", record.RequestID),\n\t\t\t}\n\t\t}\n\t\tresult, runErr := runner.executePrepared(ctx, item, evidence, started, now)\n\t\tif err := emitValidatedReplayResult(emit, result); err != nil {\n\t\t\treturn err","sourceCodeStart":547,"sourceCodeEnd":583,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/cacheengine/cachebench/replay.go#L547-L583","documentation":"In sequential replay mode, the sleep until a record's scheduled send time returned an error. The sleep function (injectable, context-aware) fails most commonly because the context was canceled while waiting, and the runner wraps that error rather than sending the request off-schedule.","triggerScenarios":"runSequential waiting for the gap to the next record's scaled timestamp when ctx (or the sleep's context) is canceled or times out; a custom sleep implementation returning its own error; a TimeScale that stretches gaps past the run's deadline.","commonSituations":"Ctrl+C during a replay with long inter-request gaps; a run-level timeout shorter than the scaled trace duration; TimeScale=1.0 (real-time pacing) on a multi-hour trace under a minutes-long deadline.","solutions":["Verify with errors.Is(err, context.Canceled) / context.DeadlineExceeded whether this is an intentional abort or a timeout.","Increase the run deadline or use a TimeScale < 1 to compress gaps so the replay fits the context budget.","If it was intentional cancellation, handle it as a clean shutdown and persist results emitted so far.","For custom sleep functions, make sure they only return on context done or elapsed time, not spurious errors."],"exampleFix":"// before\nrunner.TimeScale = 1.0 // real-time gaps exceed a 60s run deadline\nctx, cancel := context.WithTimeout(ctx, 60*time.Second)\n\n// after\nrunner.TimeScale = 0.01 // compress gaps 100x\nctx, cancel := context.WithTimeout(ctx, 10*time.Minute)","handlingStrategy":"try-catch","validationCode":"if err := ctx.Err(); err != nil {\n    return err // do not start a replay with an already-doomed context\n}","typeGuard":null,"tryCatchPattern":"if err := runner.Run(ctx, records, emit); err != nil {\n    if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {\n        // aborted mid-schedule: results emitted so far are valid; resume or exit\n    }\n    return err\n}","preventionTips":["Budget the deadline as (trace span / TimeScale) plus per-request latency and margin.","Compress long traces with a small TimeScale instead of stretching deadlines unboundedly.","Wire cancellation only to real shutdown signals."],"tags":["cachebench","context","scheduling","replay"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}