go-delve/delve · error
runtime.copystack has too many return instructions
Error message
runtime.copystack has too many return instructions
What it means
To keep stack watchpoints correct across goroutine stack growth/shrink, Delve sets a StackResizeBreakpoint at the (expected single) return instruction of runtime.copystack. findRetPC scans that function's disassembly for return instructions; if more than one RET PC is found, the code cannot know which one to instrument and aborts with 'runtime.copystack has too many return instructions'. The layout of runtime.copystack is compiler-version dependent, so a Go toolchain that emits multiple ret instructions in copystack breaks this assumption.
Source
Thrown at pkg/proc/stackwatch.go:104
if err != nil {
return err
}
retbreaklet2 := retbp2.Breaklets[len(retbp2.Breaklets)-1]
retbreaklet2.watchpoint = watchpoint
retbreaklet2.callback = woos
break
}
}
}
// Stack Resize Sentinel
retpcs, err := findRetPC(t, "runtime.copystack")
if err != nil {
return err
}
if len(retpcs) > 1 {
return errors.New("runtime.copystack has too many return instructions")
}
rszbp, err := t.SetBreakpoint(0, retpcs[0], StackResizeBreakpoint, sameGCond)
if err != nil {
return err
}
rszbreaklet := rszbp.Breaklets[len(rszbp.Breaklets)-1]
rszbreaklet.watchpoint = watchpoint
rszbreaklet.callback = func(th Thread, _ *Target) (bool, error) {
adjustStackWatchpoint(t, th, watchpoint)
return false, nil // we never want this breakpoint to be shown to the user
}
return nil
}
// clearStackWatchBreakpoints clears all accessory breakpoints forView on GitHub (pinned to a23773e6c3)
Solutions
- Upgrade or downgrade Delve to a version matched to your Go toolchain, so findRetPC's expectations of runtime.copystack match the compiled runtime
- Rebuild the program with a standard, commonly-used Go release that produces the single-return copystack layout Delve expects
- As a workaround, watch the variable's address manually via a hardware watchpoint on a non-stack variable or re-check the value manually instead of using stack watchpoints
- Check the Go version pinning in your build (go.mod toolchain directive, CI images) and align it with what your Delve version was tested against
Example fix
// before: mismatched toolchain // go 1.99 toolchain producing multi-ret copystack go build -gcflags="all=-N -l" -o app // after: pin a toolchain known to work with this Delve // go.mod: toolchain go1.22 go build -gcflags="all=-N -l" -o app
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check copystack's ret count before creating stack watchpoints
pcs, err := findRetPC(target, "runtime.copystack") // via debugger tooling
if err != nil || len(pcs) != 1 {
return fmt.Errorf("stack watchpoints unavailable: copystack has %d ret PCs", len(pcs))
} Try / catch
wp, err := client.CreateWatchpoint(scope, expr, WatchWrite)
if err != nil {
if strings.Contains(err.Error(), "too many return instructions") {
// fall back to manual polling of the variable instead of a stack watchpoint
return pollVariableInstead(expr)
}
return err
} Prevention
- Use a Go toolchain version known to work with your Delve version
- Keep Delve updated alongside Go upgrades
- Prefer watchpoints on heap-allocated variables when debugging nonstandard runtimes
- Test watchpoint creation once at session start so the failure is caught early
When it happens
Trigger: Setting a stack-allocated variable watchpoint (SetWatchpoint on a variable that lives on the goroutine stack) while the debugged binary's runtime.copystack disassembles to more than one return instruction.
Common situations: Using an unusual or very new/old Go toolchain whose runtime.copystack code shape differs from what this Delve version expects; instrumented/patched runtimes; certain optimization settings changing the function's epilogue layout.
Related errors
- break on read only not supported
- multiple errors evaluating conditions
- condition expression unreadable: %v
- can not watch %q
- could not determine location (scope is nil)
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/015bdecd0a82c4f7.
Report an issue: GitHub.