Repository navigation
runtime: nil-pointer panic in a promoted-method wrapper becomes "traceback did not unwind completely" under -race #81959
Copy link
Copy link
Closed
hunterkritik-byte/go
#2Labels
FixPendingIssues that have a fix which has not yet been reviewed or submitted.Issues that have a fix which has not yet been reviewed or submitted.compiler/runtimeIssues related to the Go compiler and/or runtime.Issues related to the Go compiler and/or runtime.release-blocker
Milestone
Description
Go version
go version go1.27.1 darwin/arm64
Output of go env in your module/workspace:
AR='ar'
CC='clang'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='clang++'
GCCGO='gccgo'
GO111MODULE=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN='/Users/<user>/go/bin'
GOCACHE='/Users/<user>/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/<user>/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=<tmp> -gno-record-gcc-switches -fno-common'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='<tmp>'
GOMODCACHE='/Users/<user>/go/pkg/mod'
GONOPROXY='<redacted>'
GONOSUMDB='<redacted>'
GOOS='darwin'
GOPACKAGESDRIVER=''
GOPATH='/Users/<user>/go'
GOPRIVATE='<redacted>'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/Users/<user>/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27.1.darwin-arm64'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/<user>/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='go1.27.1'
GOTOOLDIR='/Users/<user>/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27.1.darwin-arm64/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.27.1'
GOWORK=''
PKG_CONFIG='pkg-config'What did you do?
go run -race . on:
package main
import "fmt"
type I interface{ m() I }
type T struct{ x int }
func (t *T) m() I { return t }
// W embeds T by value, so (*W).m is a compiler-generated wrapper that
// computes &w.T before calling (*T).m; on a nil *W that faults.
type W struct{ T }
func call(i I) I {
defer func() {}()
return i.m()
}
func main() {
defer func() { fmt.Println("recovered:", recover()) }()
call((*W)(nil))
}What did you see happen?
runtime: g1: frame.sp=0xc0001a7e30 top=0xc0001a7fd0
stack=[0xc0001a6000-0xc0001a8000
fatal error: traceback did not unwind completely
runtime stack:
runtime.throw({0x100bf09c4?, 0x100ce0320?})
/Users/<user>/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27.1.darwin-arm64/src/runtime/panic.go:1243 +0x38 fp=0x16f305fd0 sp=0x16f305fa0 pc=0x100babe68
runtime.(*unwinder).finishInternal(0x16f3060d8?)
/Users/<user>/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27.1.darwin-arm64/src/runtime/traceback.go:572 +0x10c fp=0x16f306010 sp=0x16f305fd0 pc=0x100b99e0c
runtime.(*unwinder).next(0x16f3060d8?)
/Users/<user>/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27.1.darwin-arm64/src/runtime/traceback.go:452 +0x290 fp=0x16f3060a0 sp=0x16f306010 pc=0x100b99c60
runtime.(*_panic).nextFrame.func1()
/Users/<user>/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27.1.darwin-arm64/src/runtime/panic.go:1044 +0xe8 fp=0x16f306160 sp=0x16f3060a0 pc=0x100ba6198
runtime.systemstack(0x0)
/Users/<user>/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27.1.darwin-arm64/src/runtime/asm_arm64.s:379 +0x68 fp=0x16f306170 sp=0x16f306160 pc=0x100bafb28
goroutine 1 gp=0xc0000041e0 m=0 mp=0x100cf0be0 [running]:
runtime.systemstack_switch()
/Users/<user>/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27.1.darwin-arm64/src/runtime/asm_arm64.s:327 +0x8 fp=0xc0001a7c50 sp=0xc0001a7c40 pc=0x100bafaa8
runtime.(*_panic).nextFrame(0xc0001a7cb8?)
/Users/<user>/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27.1.darwin-arm64/src/runtime/panic.go:1002 +0x58 fp=0xc0001a7c90 sp=0xc0001a7c50 pc=0x100b766a8
runtime.(*_panic).nextDefer(0xc0001a7cf8)
/Users/<user>/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27.1.darwin-arm64/src/runtime/panic.go:989 +0xb8 fp=0xc0001a7cc0 sp=0xc0001a7c90 pc=0x100b76588
panic({0x100ccffa0?, 0x100ceb9e0?})
/Users/<user>/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27.1.darwin-arm64/src/runtime/panic.go:855 +0x128 fp=0xc0001a7d70 sp=0xc0001a7cc0 pc=0x100babb88
runtime.panicmem(...)
/Users/<user>/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27.1.darwin-arm64/src/runtime/panic.go:336
runtime.sigpanic()
/Users/<user>/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27.1.darwin-arm64/src/runtime/signal_unix.go:931 +0x2dc fp=0xc0001a7dd0 sp=0xc0001a7d70 pc=0x100bad6fc
main.(*W).m(0x100afe120?)
<autogenerated>:1 fp=0xc0001a7de0 sp=0xc0001a7de0 pc=0x100bea440
main.call({0x100cde650, 0x0})
/tmp/racebug/main.go:17 +0x50 fp=0xc0001a7e50 sp=0xc0001a7de0 pc=0x100bea290
main.main()
/tmp/racebug/main.go:22 +0x44 fp=0xc0001a7ea0 sp=0xc0001a7e50 pc=0x100bea344
runtime.main()
/Users/<user>/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27.1.darwin-arm64/src/runtime/proc.go:302 +0x380 fp=0xc0001a7fd0 sp=0xc0001a7ea0 pc=0x100b7a0f0
runtime.goexit({})
/Users/<user>/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.27.1.darwin-arm64/src/runtime/asm_arm64.s:1039 +0x4 fp=0xc0001a7fd0 sp=0xc0001a7fd0 pc=0x100bb1a64
What did you expect to see?
recovered: runtime error: invalid memory address or nil pointer dereference
Notes
Bisected (go1.26.0 good, go1.27.0 bad) to:
50d988e4e037d9d41ac223a62706dfea47a100e4 is the first bad commit
runtime: when panicking, skip ahead to previous panic (CL 738041, #77062)
Its parent, bf84b00, recovers in 5 of 5 runs with -race; 50d988e crashes in 5 of 5 and recovers without -race.
| toolchain | without -race | with -race |
|---|---|---|
| go1.23.12, go1.24.3, go1.26.1 (darwin/arm64) | recovers | recovers |
| go1.27.0, go1.27.1 (darwin/arm64) | recovers | fatal error |
| master 6bbd163 (darwin/arm64) | recovers | fatal error |
| golang:1.26.1 image (linux/arm64) | recovers | recovers |
| golang:1.27.1 image (linux/arm64) | recovers | fatal error |
From my testing, all of these seem to be needed:
- the fault happens inside a compiler-generated promoted-method wrapper (
main.(*W).m, forWembeddingTby value) - a frame with a defer sits between the fault and the recover (an empty
defer func() {}()is enough). Without this defer, the program behaves normally -race
This doesn't look like #81478 / #81340 / #81089: those bisect to e7a09d1, the next commit (with 50d988e as their good parent), and master, which already has the #81478 fix (CL 832244), still crashes.
Not tested on amd64.
cc @randall77
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
FixPendingIssues that have a fix which has not yet been reviewed or submitted.Issues that have a fix which has not yet been reviewed or submitted.compiler/runtimeIssues related to the Go compiler and/or runtime.Issues related to the Go compiler and/or runtime.release-blocker
Type
Projects
- StatusShow more project fieldsDone
Activity
gabyhelp commentedon Oct 2, 2026
Related Issues
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
prattmic commentedon Oct 2, 2026
cc @golang/runtime @golang/compiler
gopherbot commentedon Oct 4, 2026
Change https://go.dev/cl/844565 mentions this issue:
runtime: match deferring function when looking for linked defers in nextFrameruntime: match deferring function when looking for linked defers in n…