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

  1. Increase the waitfor duration (e.g. --waitfor-interval / longer waitfor duration flags or config)
  2. Verify the exact process name/pid the target will have (ps aux) and correct the waitfor argument
  3. Start the target process first, or launch it under dlv debug/exec instead of attach+waitfor
  4. 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

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


AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31). Data as JSON: /api/errors/86a7efbbead94280. Report an issue: GitHub.