Skip to content

runtime: nil-pointer panic in a promoted-method wrapper becomes "traceback did not unwind completely" under -race #81959

Closed
hunterkritik-byte/go
#2

Description

@LuisLSousa

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, for W embedding T by 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

Activity

  1. prattmic commented on Oct 2, 2026

    @prattmic
    Member

    cc @golang/runtime @golang/compiler

  2. added this to the Go1.28 milestone on Oct 2, 2026
  3. added
    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.
    on Oct 2, 2026
  4. gopherbot commented on Oct 4, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/844565 mentions this issue: runtime: match deferring function when looking for linked defers in nextFrame

  5. added
    FixPendingIssues that have a fix which has not yet been reviewed or submitted.
    and removed
    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.
    on Oct 6, 2026
  6. added a commit that references this issue on Oct 15, 2026
    02e6c32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

FixPendingIssues that have a fix which has not yet been reviewed or submitted.compiler/runtimeIssues related to the Go compiler and/or runtime.release-blocker

Type

No type

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions