temporalio/temporal · error

parallelsuite: assertion called on %q after Run() was called

Error message

parallelsuite: assertion called on %q after Run() was called; use the callback parameter's assertions inside Run() instead

What it means

parallelsuite's guardT wraps a testing.T and seals it once Suite.Run() spawns subtests. Any assertion method invoked on the parent guard after Run() started panics, because assertions must use the subtest callback's own t to avoid cross-subtest races.

Source

Thrown at common/testing/parallelsuite/guard.go:20

import (
	"fmt"
	"sync/atomic"
	"testing"
)

// guardT is a [require.TestingT] wrapper that prevents assertions after Run() is called.
//
// Assertions before Run() are allowed; after Run() any assertion panics.
type guardT struct {
	*testing.T
	name        string
	hasSubtests atomic.Bool
}

func (g *guardT) Helper() {
	if g.hasSubtests.Load() {
		panic(fmt.Sprintf(
			"parallelsuite: assertion called on %q after Run() was called; "+
				"use the callback parameter's assertions inside Run() instead",
			g.name,
		))
	}
	g.T.Helper()
}

func (g *guardT) Errorf(format string, args ...any) {
	if g.hasSubtests.Load() {
		g.Helper() // panics with clear message
	}
	g.T.Errorf(format, args...)
}

func (g *guardT) FailNow() {
	if g.hasSubtests.Load() {
		g.Helper() // panics with clear message

View on GitHub (pinned to bde624efd1)

Solutions

  1. Move the assertion inside the Run() callback and use the callback's t parameter.
  2. Assert before calling Run(), or capture results and assert within each subtest.
  3. Restructure shared post-subtest checks so each subtest performs its own assertions on its own t.

Example fix

// before
suite.Run("case", func(t *parallelsuite.T) { ... })
suite.Errorf("done") // panics
// after
suite.Run("case", func(t *parallelsuite.T) {
	...
	t.Errorf("done")
})
Defensive patterns

Strategy: type-guard

Type guard

func canAssertOnSuite(s *parallelsuite.Suite[X]) bool {
	return !s.TB().(*guardT).hasSubtests.Load() // or use suite API before Run()
}

Prevention

When it happens

Trigger: Calling s.Errorf(...) (or FailNow, which routes through Helper) on the suite's parent guard after s.Run(name, func(t *parallelsuite.T){...}) has been invoked.

Common situations: Deferring cleanup assertions at suite setup time that fire after Run(); helper methods capturing the suite's t in a closure and calling it inside/after Run(); assertions made between subtests.

Related errors


AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/7e48a24fa56770d6. Report an issue: GitHub.