{"id":"51df680b60d86e66","repo":"stretchr/testify","slug":"assert-must-not-be-called-before-run-or-sett","errorCode":null,"errorMessage":"'Assert' must not be called before 'Run' or 'SetT'","messagePattern":"'Assert' must not be called before 'Run' or 'SetT'","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"suite/suite.go","lineNumber":79,"sourceCode":"\t\tpanic(\"'Require' must not be called before 'Run' or 'SetT'\")\n\t}\n\treturn suite.require\n}\n\n// Assert returns an assert context for suite. Normally, you can call:\n//\n//\tsuite.NoError(err)\n//\n// But for situations where the embedded methods are overridden (for example,\n// you might want to override assert.Assertions with require.Assertions), this\n// method is provided so you can call:\n//\n//\tsuite.Assert().NoError(err)\nfunc (suite *Suite) Assert() *assert.Assertions {\n\tsuite.mu.Lock()\n\tdefer suite.mu.Unlock()\n\tif suite.Assertions == nil {\n\t\tpanic(\"'Assert' must not be called before 'Run' or 'SetT'\")\n\t}\n\treturn suite.Assertions\n}\n\nfunc recoverAndFailOnPanic(t *testing.T) {\n\tt.Helper()\n\tr := recover()\n\tfailOnPanic(t, r)\n}\n\nfunc failOnPanic(t *testing.T, r interface{}) {\n\tt.Helper()\n\tif r != nil {\n\t\tt.Errorf(\"test panicked: %v\\n%s\", r, debug.Stack())\n\t\tt.FailNow()\n\t}\n}\n","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/stretchr/testify/blob/001eb7946baf451879253643e4ce4b38eaa0d4a7/suite/suite.go#L61-L97","documentation":"suite.Assert() (suite/suite.go:75-82) returns the embedded *assert.Assertions handle allocated in SetT (suite.go:42-48). It panics with this message when Assert() is called on a suite whose SetT has not run — i.e. suite.Assertions is still nil. The library panics here (rather than returning nil) to surface the lifecycle violation at the call site instead of letting it become an opaque nil-deref later. It is the assert-side twin of the Require() guard.","triggerScenarios":"Calling suite.Assert() (or this.Assert() on an embedded Suite) before suite.Run(t, &s) or an explicit SetT(t). Concretely: (a) instantiating &MySuite{} and invoking methods directly in a t.Run-registered closure instead of via suite.Run; (b) calling Assert() from SetupAllSuite when the suite was registered without going through suite.Run; (c) a suite embedded by value or copied so SetT's write to suite.Assertions never reaches the receiver the test reads; (d) overriding embedded assert.Assertions and forgetting that Assert() still depends on SetT having populated it.","commonSituations":"Ad-hoc suite usage where the author wraps t.Run themselves and bypasses suite.Run; refactoring a test to embed suite.Suite and calling s.Assert() in a helper invoked from TestMain; copying a suite value (e.g. *s = *original) before Run; embedding suite.Suite as a value field rather than pointer, so SetT's assignment is lost on the next receiver copy.","solutions":["Enter the suite via suite.Run(t, &MySuite{}) so SetT runs first; Assert() is then safe inside SetupSuite/BeforeTest/Test*/TearDown.","If you cannot use suite.Run, call s.SetT(t) manually before any Assert()/Require() call.","Pass the suite by pointer (&MySuite{}); never copy a suite value, since SetT mutates fields the copies won't see.","Avoid calling Assert() from goroutines or helpers that may execute before SetT; pass the suite pointer in after initialization."],"exampleFix":"// before\nfunc TestBar(t *testing.T) {\n    s := MySuite{}           // value, never Run\n    s.Assert().Equal(1, 1)   // panic: Assert before Run/SetT\n}\n\n// after\nfunc TestBar(t *testing.T) {\n    suite.Run(t, &MySuite{}) // pointer; SetT populates Assertions\n}\nfunc (s *MySuite) TestThing() { s.Assert().Equal(1, 1) }","handlingStrategy":"validation","validationCode":"// Assert() is only safe after SetT populated suite.Assertions;\n// use T() as the public readiness probe.\nfunc safeAssert(s *suite.Suite) (*assert.Assertions, error) {\n    if s.T() == nil {\n        return nil, errors.New(\"suite not initialized: call suite.Run or SetT first\")\n    }\n    return s.Assert(), nil\n}","typeGuard":"// Narrow on the readiness signal before any embedded-method override path.\nfunc assertReady(s TestingSuite) bool {\n    type tGetter interface{ T() *testing.T }\n    g, ok := s.(tGetter)\n    return ok && g.T() != nil\n}\n\n// usage: if !assertReady(s) { t.Fatal(\"start suite with suite.Run(t, &MySuite{})\") }","tryCatchPattern":"// Wrap overrides that call Assert() so a lifecycle slip becomes a clear failure.\nfunc safeAssertCall(t *testing.T, s *MySuite, fn func(*assert.Assertions)) {\n    defer func() {\n        if r := recover(); r != nil {\n            t.Fatalf(\"Assert misuse: %v\\nEnsure the suite is started with suite.Run(t, &MySuite{}).\", r)\n        }\n    }()\n    fn(s.Assert())\n}","preventionTips":["Enter the suite only through suite.Run(t, &MySuite{}); do not register suite methods via t.Run.","Pass &MySuite{} (pointer); copying a suite value discards SetT's write to Assertions.","When overriding embedded assert.Assertions (e.g. to swap for require), still rely on SetT having run; do not assume the field is populated outside the lifecycle.","Keep Assert()/Require() calls inside Setup*/BeforeTest/Test*/AfterTest/TearDown* hooks, where SetT is guaranteed."],"tags":["testify","suite","lifecycle","panic","go"],"analyzedSha":"001eb7946baf451879253643e4ce4b38eaa0d4a7","analyzedAt":"2026-08-04T21:49:58.715Z","schemaVersion":2}