go-delve/delve · error · ErrNotRecorded
not a recording
Error message
not a recording
What it means
ErrNotRecorded is the sentinel error returned by delve's proc layer when an action that only makes sense on a recorded (traced) program is requested on a live process. Recording-backed operations (reverse stepping, restarts, time travel) require the debugger to have captured execution history, which live backends do not have. The proc layer returns this sentinel so callers can detect the unsupported direction/mode explicitly.
Source
Thrown at pkg/proc/target.go:21
import (
"errors"
"fmt"
"go/constant"
"os"
"sort"
"strings"
"sync"
"github.com/go-delve/delve/pkg/dwarf/op"
"github.com/go-delve/delve/pkg/goversion"
"github.com/go-delve/delve/pkg/logflags"
"github.com/go-delve/delve/pkg/proc/internal/ebpf"
)
var (
// ErrNotRecorded is returned when an action is requested that is
// only possible on recorded (traced) programs.
ErrNotRecorded = errors.New("not a recording")
// ErrNoRuntimeAllG is returned when the runtime.allg list could
// not be found.
ErrNoRuntimeAllG = errors.New("could not find goroutine array")
// ErrProcessDetached indicates that we detached from the target process.
ErrProcessDetached = errors.New("detached from the process")
)
type LaunchFlags uint8
const (
LaunchForeground LaunchFlags = 1 << iota
LaunchDisableASLR
)
// Target represents the process being debugged.
type Target struct {View on GitHub (pinned to a23773e6c3)
Solutions
- Only enable reverse-debugging operations when the session was launched from a recording (dlv replay / rr backend)
- Check the backend/recording state before calling ChangeDirection or Restart
- Handle the sentinel error by falling back to forward-only execution
- Use `so`/forward stepping instead of reverse commands on live targets
Example fix
// before
tgrp.ChangeDirection(proc.Backward) // panics flow with 'not a recording'
// after
if _, err := tgrp.Valid(); err == nil && debuggerIsRecording {
err = tgrp.ChangeDirection(proc.Backward)
} else {
return fmt.Errorf("reverse stepping requires a recording (use dlv replay)")
} Defensive patterns
Strategy: try-catch
Validate before calling
// check session kind before reverse ops
if !isRecordingSession(tgrp) {
return fmt.Errorf("reverse operations require a recorded target")
} Type guard
func isRecordingSession(t *proc.TargetGroup) bool {
_, err := t.Valid()
return err == nil && t.Selected != nil && t.Selected.Recording() != nil
} Try / catch
err := tgrp.ChangeDirection(proc.Backward)
if errors.Is(err, proc.ErrNotRecorded) {
// fall back to forward-only stepping
} Prevention
- Only expose reverse-debug commands when launched via dlv replay/rr
- Check recording support in UI before enabling rewind buttons
- Treat ErrNotRecorded as a capability flag, not a failure
When it happens
Trigger: Calling TargetGroup.ChangeDirection (e.g. setting direction to Backward or issuing rev-step/rev-next) or Restart on a process attached via the native or gdbserial (live) backend, since dummyRecordingManipulation.Restart always returns ErrNotRecorded.
Common situations: A user issues 'rewind', 'restart' or reverse-continue in the terminal/DAP client while debugging a normal 'dlv debug'/'dlv attach' session instead of a 'dlv replay' core/trace recording; IDE plugins that expose reverse-debug buttons unconditionally.
Related errors
- could not decode first frame
- unable to find function context
- unable to find locals: no debug information present in binar
- no address for escaped variable
- can not assign to function expression
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/dcccecbd80815a28.
Report an issue: GitHub.