go-delve/delve · error
waitfor duration expired
Error message
waitfor duration expired
What it means
WaitFor polls for a process matching a name/pid for up to waitFor.Duration. If the deadline elapses without finding a matching process, it returns 'waitfor duration expired'. It is used by Attach with the --waitfor flag.
Source
Thrown at pkg/proc/native/proc.go:89
bi: proc.NewBinaryInfo(runtime.GOOS, runtime.GOARCH),
}
}
// WaitFor waits for a process as specified by waitFor.
func WaitFor(waitFor *proc.WaitFor) (int, error) {
t0 := time.Now()
seen := make(map[int]struct{})
for (waitFor.Duration == 0) || (time.Since(t0) < waitFor.Duration) {
pid, err := waitForSearchProcess(waitFor.Name, seen)
if err != nil {
return 0, err
}
if pid != 0 {
return pid, nil
}
time.Sleep(waitFor.Interval)
}
return 0, errors.New("waitfor duration expired")
}
// BinInfo will return the binary info struct associated with this process.
func (dbp *nativeProcess) BinInfo() *proc.BinaryInfo {
return dbp.bi
}
// StartCallInjection notifies the backend that we are about to inject a function call.
func (dbp *nativeProcess) StartCallInjection() (func(), error) { return func() {}, nil }
// detachWithoutGroup is a helper function to detach from a process which we
// haven't added to a process group yet.
func detachWithoutGroup(dbp *nativeProcess, kill bool) error {
grp := &processGroup{procs: []*nativeProcess{dbp}}
return grp.Detach(dbp.pid, kill)
}
// Detach from the process being debugged, optionally killing it.View on GitHub (pinned to a23773e6c3)
Solutions
- Increase the waitfor duration (e.g. --waitfor-interval / longer waitfor duration flags or config)
- Verify the exact process name/pid the target will have (ps aux) and correct the waitfor argument
- Start the target process first, or launch it under dlv debug/exec instead of attach+waitfor
- Check that the target isn't failing to start (its own startup error) — fix the target launch
Example fix
// before dlv attach --waitfor myserver // after (allow more time and poll faster) dlv attach --waitfor myserver --waitfor-duration 60s --waitfor-interval 100ms
Defensive patterns
Strategy: retry
Validate before calling
// confirm a matching process exists (or will) before attach --waitfor
func processExists(name string) bool {
out, err := exec.Command("pgrep", "-x", name).Output()
return err == nil && len(strings.TrimSpace(string(out))) > 0
}
if !processExists("myserver") {
// use a generous waitfor duration instead of the default
} Try / catch
pid, err := native.WaitFor(waitFor)
if err != nil {
if strings.Contains(err.Error(), "waitfor duration expired") {
return fmt.Errorf("no process matching %q appeared within %s; increase duration or check the process name", waitFor.Name, waitFor.Duration)
}
return err
} Prevention
- Set --waitfor-duration generously relative to the target's startup time
- Double-check the exact executable/process name used in waitfor
- Tune --waitfor-interval to poll frequently enough to catch short-lived matches
- Ensure the target actually starts (check its logs for startup failures)
When it happens
Trigger: dlv attach --waitfor <name/pid> where no process matching the pattern appears within the configured duration (default ~ short timeout) — the loop's time check expires and pid remains 0.
Common situations: Attaching to a program that starts slower than the waitfor timeout; misspelled process name in waitfor; process crashing before it can be found; waitfor interval/duration flags misconfigured (duration shorter than startup time).
Related errors
- waitfor not implemented
- cannot restart process Delve did not create
- could not determine executable path: %v
- qThreadStopInfo mismatch, requested %s got %s
- could not attach to %d
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/86a7efbbead94280.
Report an issue: GitHub.