go-delve/delve · error
no match found using regexp '%s' in /proc/%d/stat
Error message
no match found using regexp '%s' in /proc/%d/stat
What it means
After reading /proc/<pid>/stat, delve applies the regexp "<pid>\\s*\\((.*)\\)" to extract the command name. If FindSubmatch finds no match, it returns this error including the full expression and pid. This means the stat file's first field is not the expected pid or the file is malformed/truncated.
Source
Thrown at pkg/proc/native/proc_linux.go:288
comm, err := os.ReadFile(fmt.Sprintf("/proc/%d/comm", dbp.pid))
if err == nil {
// removes newline character
comm = bytes.TrimSuffix(comm, []byte("\n"))
}
if len(comm) <= 0 {
stat, err := os.ReadFile(fmt.Sprintf("/proc/%d/stat", dbp.pid))
if err != nil {
return "", fmt.Errorf("could not read proc stat: %v", err)
}
expr := fmt.Sprintf("%d\\s*\\((.*)\\)", dbp.pid)
rexp, err := regexp.Compile(expr)
if err != nil {
return "", fmt.Errorf("regexp compile error: %v", err)
}
match := rexp.FindSubmatch(stat)
if match == nil {
return "", fmt.Errorf("no match found using regexp '%s' in /proc/%d/stat", expr, dbp.pid)
}
comm = match[1]
}
dbp.os.comm = strings.ReplaceAll(string(comm), "%", "%%")
return getCmdLine(dbp.pid), nil
}
func (dbp *nativeProcess) GetBufferedTracepoints() []ebpf.RawUProbeParams {
if dbp.os.ebpf == nil {
return nil
}
return dbp.os.ebpf.GetBufferedTracepoints()
}
// kill kills the target process.
func (procgrp *processGroup) kill(dbp *nativeProcess) error {
if ok, _ := dbp.Valid(); !ok {View on GitHub (pinned to a23773e6c3)
Solutions
- Re-run the attach; a race with process exit is the most common cause.
- Inspect /proc/<pid>/stat manually to confirm the first field equals the pid.
- If running under gVisor/LXC or other sandboxed procfs, test on a standard kernel or use a newer sandbox runtime with conformant procfs.
- Run delve as root so it reads the correct process's stat rather than failing on visibility tricks.
Example fix
// before
_ = debugger.Attach(pid, nil) // no match found using regexp '1234\s*\((.*)\)' in /proc/1234/stat
// after
stat, _ := os.ReadFile(fmt.Sprintf("/proc/%d/stat", pid))
if !strings.HasPrefix(string(stat), strconv.Itoa(pid)+" ") {
return fmt.Errorf("pid %d vanished or was reused before attach", pid)
}
_ = debugger.Attach(pid, nil) Defensive patterns
Strategy: retry
Validate before calling
// confirm stat file shape matches the pid before attach
func statLooksSane(pid int) bool {
b, err := os.ReadFile(fmt.Sprintf("/proc/%d/stat", pid))
return err == nil && strings.HasPrefix(string(b), strconv.Itoa(pid)+" ")
} Try / catch
err := debugger.Attach(pid, nil)
if err != nil && strings.Contains(err.Error(), "no match found using regexp") {
// likely exit/pid-reuse race or non-standard procfs; retry once
err = debugger.Attach(pid, nil)
} Prevention
- Retry attach once — the dominant cause is an exit/pid-reuse race.
- Check /proc/<pid>/stat manually when failures repeat.
- Beware sandboxed procfs (gVisor/LXC) with non-standard stat layout.
- Run as root to rule out visibility-induced misreads.
When it happens
Trigger: initialize's comm fallback parses a stat file whose contents do not start with the traced pid — typically because the process exited and the pid was reused, or a race left a truncated read, or the kernel is not Linux-standard procfs (LXC/gVisor variants).
Common situations: Attaching in containers/sandboxes (gVisor, LXC) with non-conforming procfs; pid churn in busy CI environments; reading /proc for a zombie or being-reaped process whose stat layout differs.
Related errors
- could not read proc stat: %v
- regexp compile error: %v
- malformed /proc/pid/maps on line %d: %q (wrong number of fie
- malformed /proc/pid/maps on line %d: %q (bad first field)
- malformed /proc/pid/maps on line %d: %q (%v)
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/7b6d6a77cef24b90.
Report an issue: GitHub.