"go test -v" doesn't display panic stack traces

143 views
Skip to first unread message

Tom Limoncelli

unread,
Jun 15, 2026, 6:39:29 PM (3 days ago) Jun 15
to golang-nuts
Is there a way to get "go test" to display the stack trace when the function under test panics?

I've written a function that (for purposes of this demo) panics if passed true:

The output on go playground looks like this:

=== RUN   TestMyFunc
=== RUN   TestMyFunc/good
=== RUN   TestMyFunc/panic
--- FAIL: TestMyFunc (0.00s)
    --- PASS: TestMyFunc/good (0.00s)
    --- FAIL: TestMyFunc/panic (0.00s)
panic: assignment to entry in nil map [recovered, repanicked]

goroutine 17 [running]:
testing.tRunner.func1.2({0x55a800, 0x6cac00})
/usr/local/go-faketime/src/testing/testing.go:1974 +0x232
testing.tRunner.func1()
/usr/local/go-faketime/src/testing/testing.go:1977 +0x349
panic({0x55a800?, 0x6cac00?})
/usr/local/go-faketime/src/runtime/panic.go:860 +0x13a
play.MyFunc(...)
/tmp/sandbox252008880/prog_test.go:14
play.TestMyFunc.func1(0x3e938180e008?)
/tmp/sandbox252008880/prog_test.go:33 +0x33
testing.tRunner(0x3e938180e008, 0x3e9381800000)
/usr/local/go-faketime/src/testing/testing.go:2036 +0xea
created by testing.(*T).Run in goroutine 7
/usr/local/go-faketime/src/testing/testing.go:2101 +0x4c5

Program exited.


However when I run this on my personal machine (go1.26.4, Macos 26.5.1) the system goes into an infinite loop until I press CTRL-C.  At that point it exits but never shows the stack trace:
 
$ go test -v
=== RUN   TestMyFunc
=== RUN   TestMyFunc/good
=== RUN   TestMyFunc/panic
--- FAIL: TestMyFunc (0.00s)
    --- PASS: TestMyFunc/good (0.00s)
    --- FAIL: TestMyFunc/panic (0.00s)
^Csignal: interrupt
FAIL ptest 4.924s


As you can imagine, debugging an unknown panic is difficult without the stack trace indicating the problematic line.  Delve has the same behavior.

Is there a way to have "go test" display the stack trace like Go playground does?

Also... the fact that a panic sends Go testing into an infinite loop sounds like a bug.  Is this just my environment, or can others reproduce this?

Thanks in advance!
Tom

Jason E. Aten

unread,
Jun 15, 2026, 7:24:21 PM (3 days ago) Jun 15
to golang-nuts
Be sure your env has GOTRACEBACK set to "single" or "all" or "system" (see https://pkg.go.dev/runtime) and not "none". Panic usually shows the trace by default, but I suspect t.Run() may be covering it up so I would try on just a simple raw func TestOne(t *testing.T) {...} first. It is possible to have some of the layers of test infrastructure hide things from you, but I couldn't tell you exactly how, so start simple.

My usual way to halt a Go program and get a stack trace is to send SIGQUIT using "pkill -QUIT project.test". 

kill -QUIT also kills the program though, which is fine if it is deadlocked and you are trying to figure out where. But if you want to keep it alive and look at a goroutine stack snapshot, you can start the program with pprof sampling as described https://pkg.go.dev/net/http/pprof and then opening a browser and hitting the port like http://localhost:6060; if you did:

import _ "net/http/pprof"
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()

Tom Limoncelli

unread,
Jun 15, 2026, 7:46:19 PM (3 days ago) Jun 15
to Jason E. Aten, golang-nuts
Thanks for the fast reply!

Sadly GOTRACEBACK=all (and other settings) didn't change the output.   Even GOTRACEBACK=crash did nothing.

The fact that this causes an infinite loop (or maybe a deadlock) indicates this is not the intended behavior.

Tom


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/216b0486-4520-4b5f-a2e4-6286e494772fn%40googlegroups.com.

Jason E. Aten

unread,
Jun 16, 2026, 12:41:53 AM (2 days ago) Jun 16
to golang-nuts
if you give a full reproducer, we can probably help. Without that there's nothing we can suggest
except that, "your example works for me". I attached a transcript to this playground of what I see when
I run on darwin/amd64 Sonoma with go v1.25.6:

Brian Candler

unread,
Jun 16, 2026, 4:05:50 AM (2 days ago) Jun 16
to golang-nuts
On Monday, 15 June 2026 at 23:39:29 UTC+1 Tom Limoncelli wrote:
However when I run this on my personal machine (go1.26.4, Macos 26.5.1) the system goes into an infinite loop until I press CTRL-C.

I can't reproduce, and my system is similar to yours. I don't know what "go-faketime" is, and I wonder if that's the problem. I'm using go installed via homebrew.

% go version
go version go1.26.3 darwin/arm64
% cat main_test.go
package main

import (
"testing"
)

type MyStruct struct {
M map[string]string
}

func MyFunc(b bool) {
m := &MyStruct{}
if b {
m.M["foo"] = "foo" // panic. Uninitialized map!
} else {
if m.M == nil {
m.M = map[string]string{}
}
m.M["foo"] = "foo" // no panic
}
}

func TestMyFunc(t *testing.T) {
tests := []struct {
name string
data bool
}{
{"good", false},
{"panic", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
MyFunc(tt.data)
})
}
}
% go mod init example
go: creating new go.mod: module example
go: to add module requirements and sums:
go mod tidy
% go mod tidy
% ls -l
total 16
-rw-r--r--  1 brian  staff   26 16 Jun 09:00 go.mod
-rw-r--r--  1 brian  staff  502 16 Jun 09:00 main_test.go
% go test -v .

=== RUN   TestMyFunc
=== RUN   TestMyFunc/good
=== RUN   TestMyFunc/panic
--- FAIL: TestMyFunc (0.00s)
    --- PASS: TestMyFunc/good (0.00s)
    --- FAIL: TestMyFunc/panic (0.00s)
panic: assignment to entry in nil map [recovered, repanicked]

goroutine 37 [running]:
testing.tRunner.func1.2({0x102ea2ca0, 0x102eecc40})
/opt/homebrew/Cellar/go/1.26.3/libexec/src/testing/testing.go:1974 +0x1a0
testing.tRunner.func1()
/opt/homebrew/Cellar/go/1.26.3/libexec/src/testing/testing.go:1977 +0x318
panic({0x102ea2ca0?, 0x102eecc40?})
/opt/homebrew/Cellar/go/1.26.3/libexec/src/runtime/panic.go:860 +0x12c
example.MyFunc(...)
/Users/brian/tmp/zzz/main_test.go:14
example.TestMyFunc.func1(0x46a78c0626c8?)
/Users/brian/tmp/zzz/main_test.go:33 +0x40
testing.tRunner(0x46a78c0626c8, 0x46a78c030200)
/opt/homebrew/Cellar/go/1.26.3/libexec/src/testing/testing.go:2036 +0xc4
created by testing.(*T).Run in goroutine 35
/opt/homebrew/Cellar/go/1.26.3/libexec/src/testing/testing.go:2101 +0x3a8
FAIL example 0.218s
FAIL


Tom Limoncelli

unread,
Jun 17, 2026, 2:01:56 PM (23 hours ago) Jun 17
to Brian Candler, golang-nuts
Problem solved!

For some reason I could only reproduce this on my main macOS laptop, but not on others.  I uninstalled and re-installed Go (using Homebrew) and now it works.

I have no idea what caused the problem, but I figured I should post the solution (for what it is) in case anyone else encounters it.

Thanks, Brian and Jason, for trying to repro. Knowing others couldn't repro the problem pointed me in the right direction.

Best,
Tom


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages