{"record":{"id":"706f203d89785676","repo":"JuliusBrussee/caveman","slug":"cachebench-replay-preparation-interrupted-w","errorCode":null,"errorMessage":"cachebench: replay preparation interrupted: %w","messagePattern":"cachebench: replay preparation interrupted: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cacheengine/cachebench/replay.go","lineNumber":505,"sourceCode":"\t}\n\tanchorTrace, _ := time.Parse(time.RFC3339Nano, records[0].At)\n\tanchorReal := now().UTC()\n\tif runner.Limits.MaxConcurrency == 1 {\n\t\treturn runner.runSequential(ctx, prepared, anchorTrace, anchorReal, now, sleep, emit)\n\t}\n\treturn runner.runConcurrent(ctx, prepared, anchorTrace, anchorReal, now, sleep, emit)\n}\n\ntype preparedReplay struct {\n\trecord    TraceRecord\n\toptimized cacheengine.NativeResult\n}\n\nfunc (runner ReplayRunner) prepare(ctx context.Context, records []TraceRecord) ([]preparedReplay, error) {\n\tprepared := make([]preparedReplay, 0, len(records))\n\tfor _, record := range records {\n\t\tif err := ctx.Err(); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"cachebench: replay preparation interrupted: %w\", err)\n\t\t}\n\t\tnative, err := record.NativeRequest()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\toptimized, err := runner.Engine.Optimize(ctx, native)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"cachebench: optimize request %q: %w\", record.RequestID, err)\n\t\t}\n\t\tequivalent := bytes.Equal(native.Body, optimized.Body)\n\t\tif optimized.Applied {\n\t\t\tequivalent = ModelVisibleEquivalent(native.Body, optimized.Body)\n\t\t}\n\t\tif !equivalent {\n\t\t\treturn nil, &ReplayRunError{\n\t\t\t\tRequestID: record.RequestID, FailureCode: \"model_visible_mismatch\",\n\t\t\t\tErr: fmt.Errorf(\"cachebench: request %q failed model-visible equivalence\", record.RequestID),\n\t\t\t}","sourceCodeStart":487,"sourceCodeEnd":523,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/cacheengine/cachebench/replay.go#L487-L523","documentation":"The context passed to ReplayRunner.prepare was canceled or expired while it was looping over trace records preparing optimized bodies. Preparation checks ctx.Err() between records and wraps it with this message, so no partial results are used.","triggerScenarios":"Canceling the parent context (ctx cancel, timeout on the Run call) while prepare is iterating records; a deadline shorter than the time Engine.Optimize needs for the whole trace; SIGINT handlers that cancel the run context.","commonSituations":"A command wrapper with a --timeout flag that fires during long replays; test code with context.WithTimeout too tight for large traces; user Ctrl+C mid-run propagating a cancel.","solutions":["Check what canceled the context: errors.Is(err, context.DeadlineExceeded) vs context.Canceled tells you timeout vs explicit cancel.","Raise or remove the deadline on the Run/prepare context for large traces.","If cancellation was intentional (Ctrl+C, shutdown), treat this as a clean abort and discard partial state.","Speed up preparation (fewer records, faster Engine) so the window for cancellation shrinks."],"exampleFix":"// before\nctx, cancel := context.WithTimeout(ctx, 5*time.Second) // prepare of 10k records exceeds it\n\n// after\nctx, cancel := context.WithTimeout(ctx, 10*time.Minute)\ndefer cancel()","handlingStrategy":"try-catch","validationCode":"if err := ctx.Err(); err != nil {\n    return fmt.Errorf(\"refusing to start replay: %w\", err)\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        // treat as aborted run; persist already-emitted results and exit cleanly\n    }\n    return err\n}","preventionTips":["Size context deadlines to trace length divided by TimeScale, with headroom.","Cancel the run context only via your shutdown signal, and defer cancel() until after Run returns.","Estimate prepare cost (records x per-record Optimize latency) before choosing a timeout."],"tags":["cachebench","context","cancellation","replay"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}