stretchr/testify · error
'Require' must not be called before 'Run' or 'SetT'
Error message
'Require' must not be called before 'Run' or 'SetT'
What it means
suite.Require() (suite/suite.go:57-64) returns the per-suite *require.Assertions handle, which is only allocated inside SetT (suite.go:42-48). The library panics with this message when Require() is invoked on a suite whose SetT has never run, because returning a nil *require.Assertions would just defer the failure to a nil-pointer deref deeper in the test. The panic pins the misuse to the exact call site and tells the author the suite lifecycle wasn't entered.
Source
Thrown at suite/suite.go:61
suite.mu.Lock()
defer suite.mu.Unlock()
suite.t = t
suite.Assertions = assert.New(t)
suite.require = require.New(t)
}
// SetS needs to set the current test suite as parent
// to get access to the parent methods
func (suite *Suite) SetS(s TestingSuite) {
suite.s = s
}
// Require returns a require context for suite.
func (suite *Suite) Require() *require.Assertions {
suite.mu.Lock()
defer suite.mu.Unlock()
if suite.require == nil {
panic("'Require' must not be called before 'Run' or 'SetT'")
}
return suite.require
}
// Assert returns an assert context for suite. Normally, you can call:
//
// suite.NoError(err)
//
// But for situations where the embedded methods are overridden (for example,
// you might want to override assert.Assertions with require.Assertions), this
// method is provided so you can call:
//
// suite.Assert().NoError(err)
func (suite *Suite) Assert() *assert.Assertions {
suite.mu.Lock()
defer suite.mu.Unlock()
if suite.Assertions == nil {
panic("'Assert' must not be called before 'Run' or 'SetT'")View on GitHub (pinned to 001eb7946b)
Solutions
- Drive the suite through the framework entrypoint: call suite.Run(t, &MySuite{}) once in your top-level TestXxx, and let it invoke SetupSuite/SetupTest/Test*/TearDown — by the time those run, SetT has executed and Require() is safe.
- If you construct the suite yourself, call s.SetT(t) explicitly before any Require()/Assert() use.
- Always pass a pointer (&MySuite{}) to suite.Run; embedding suite.Suite by value plus copying will leave require nil on the copy.
- Move any Require()/Assert() calls out of goroutines spawned before SetT, or pass the already-initialized suite by pointer into the goroutine.
Example fix
// before
func TestFoo(t *testing.T) {
s := &MySuite{}
s.SetupSuite() // user-invoked; SetT never ran
s.Require().Equal(1, 1) // panic: Require before Run/SetT
}
// after
func TestFoo(t *testing.T) {
suite.Run(t, &MySuite{}) // SetT runs first; Require() safe inside SetupSuite/Test*
}
// inside the suite:
func (s *MySuite) SetupSuite() { s.Require().Equal(1, 1) } Defensive patterns
Strategy: validation
Validate before calling
// Guard before calling Require() on a suite whose lifecycle you don't control.
func safeRequire(s *suite.Suite) (*require.Assertions, error) {
// Suite.require is private; the only public signal is T().
if s.T() == nil {
return nil, errors.New("suite not initialized: call suite.Run or SetT first")
}
return s.Require(), nil
} Type guard
// Type-narrow on the suite interface rather than guarding Require each time:
// only enter suite-internal helpers when the framework has set T.
func suiteReady(s TestingSuite) bool {
type tGetter interface{ T() *testing.T }
g, ok := s.(tGetter)
return ok && g.T() != nil
}
// usage: if !suiteReady(s) { t.Skip("suite not run via suite.Run") } Try / catch
// Convert the panic into a test failure at a controlled boundary.
func safeRequireCall(t *testing.T, s *MySuite, fn func(*require.Assertions)) {
defer func() {
if r := recover(); r != nil {
t.Fatalf("Require misuse: %v\nEnsure the suite is started with suite.Run(t, &MySuite{}).", r)
}
}()
fn(s.Require())
} Prevention
- Always enter suites via suite.Run(t, &MySuite{}) and never wrap suite methods in your own t.Run; the framework owns SetT.
- Pass the suite by pointer; never copy a *suite.Suite value.
- Reserve Require()/Assert() for suite-lifecycle methods (Setup*/Test*/TearDown*) — not for TestMain or package-level helpers.
- Lint for `&suite.Suite{}` or `MySuite{}` literals outside suite.Run; treat them as smells.
When it happens
Trigger: Calling suite.Require() (or this.Require() from an embedded Suite) before suite.Run(t, &s) or an explicit SetT(t) has executed. Concretely: (a) constructing &MySuite{} and calling its methods in a plain func(t *testing.T) without suite.Run; (b) calling Require() inside SetupSuite/SetupTest of a suite that was registered via t.Run(...) instead of suite.Run(t, ...); (c) calling Require() from a goroutine spawned in BeforeTest that races ahead of SetT, or after manually zeroing the suite; (d) embedding *suite.Suite by value and copying it before Run wires the receiver.
Common situations: Migrating a flat *testing.T test to the suite model and forgetting to swap t.Run for suite.Run; subtest registered via t.Run(name, s.MyTest) reading suite.Require() inside MyTest; refactoring SetupAllSuite logic into a helper invoked from TestMain where no T exists; copying a suite struct value instead of passing a pointer (SetT mutates the receiver, so a copy stays uninitialized).
Related errors
- 'Assert' must not be called before 'Run' or 'SetT'
- assert: arguments: Bool(%d) failed because object wasn't cor
- test failed and t is missing `FailNow()`
- Reset() is deprecated
- Copy() is deprecated
AI-assisted analysis of stretchr/testify@001eb7946b (2026-08-04).
Data as JSON: /data/errors/a3c023d9df83ca16.json.
Report an issue: GitHub.