go-delve/delve · error · errSPDecreased
corrupted defer list: SP decreased
Error message
corrupted defer list: SP decreased
What it means
errSPDecreased is returned while following the runtime defer linked list when the SP of a subsequent defer node is lower than the previous one. Since defers are pushed FIFO with SP monotonically increasing down the list, a decreasing SP means the list is corrupted (bad pointers, stale memory).
Source
Thrown at pkg/proc/stack.go:1022
break
}
if len(d.rangefunc) > maxRangeFuncDefers {
// We don't have a way to know for sure that we haven't gone completely off-road while loading this list so limit it to an arbitrary maximum size.
break
}
hd = hd.link
}
}
}
}
}
// errSPDecreased is used when (*Defer).Next detects a corrupted linked
// list, specifically when after following a link pointer the value of SP
// decreases rather than increasing or staying the same (the defer list is a
// FIFO list, nodes further down the list have been added by function calls
// further down the call stack and therefore the SP should always increase).
var errSPDecreased = errors.New("corrupted defer list: SP decreased")
// Next returns the next defer in the linked list
func (d *Defer) Next() *Defer {
if d.link == nil {
return nil
}
d.link.load(true)
if d.link.SP < d.SP {
d.link.Unreadable = errSPDecreased
}
return d.link
}
func (d *Defer) topdefer() *Defer {
if len(d.rangefunc) > 0 {
return d.rangefunc[0]
}
return dView on GitHub (pinned to a23773e6c3)
Solutions
- Update delve to a version matching the target's Go toolchain version
- Re-read the goroutine state while the target is stopped consistently (ensure the process is halted)
- Verify the target Go version is supported by this delve build
- If reading a core dump, confirm the core was produced by the same binary/build
Example fix
// before dlv attach <pid> // delve built for Go 1.21, target built with Go 1.24 // after go install github.com/go-delve/delve/cmd/dlv@latest && dlv attach <pid>
Defensive patterns
Strategy: try-catch
Validate before calling
// ensure target is stopped and delve matches Go version
out, _ := exec.Command("go", "version", "-m", binaryPath).Output()
checkDelveSupportsGoVersion(string(out)) Try / catch
frames, err := stacktraceWithDefers(g)
if err != nil && strings.Contains(err.Error(), "corrupted defer list") {
log.Printf("defer list corrupted for goroutine %d; skipping defer analysis", g.ID)
return stacktraceWithoutDefers(g)
} Prevention
- Keep delve version in sync with the target's Go toolchain version
- Only read runtime structures while the target is fully stopped
- Rebuild or re-dump corrupted core files from the same binary build
When it happens
Trigger: Iterating defers during stack tracing or panic/unwind analysis (Defer.Next) on a goroutine whose defer linked list contains garbage — e.g. reading a half-updated runtime structure, wrong runtime layout for the Go version, or corrupted stack memory.
Common situations: Attaching to a Go binary whose version's runtime struct layout differs from what delve expects; reading defers of a goroutine running concurrently while the target mutates them; corrupted core dumps.
Related errors
- negative maximum stack depth
- architectural frame rules are unsupported
- could not find goroutine array
- map index out of bounds
- maximum len exceeded (%d) reading %s
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/ba08154f84bd1a35.
Report an issue: GitHub.