{"id":"c98d46fb286c705f","repo":"stretchr/testify","slug":"test-failed-and-t-is-missing-failnow","errorCode":null,"errorMessage":"test failed and t is missing `FailNow()`","messagePattern":"test failed and t is missing `FailNow\\(\\)`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"assert/assertions.go","lineNumber":361,"sourceCode":"}\n\n// FailNow fails test\nfunc FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {\n\tif h, ok := t.(tHelper); ok {\n\t\th.Helper()\n\t}\n\tFail(t, failureMessage, msgAndArgs...)\n\n\t// We cannot extend TestingT with FailNow() and\n\t// maintain backwards compatibility, so we fallback\n\t// to panicking when FailNow is not available in\n\t// TestingT.\n\t// See issue #263\n\n\tif t, ok := t.(failNower); ok {\n\t\tt.FailNow()\n\t} else {\n\t\tpanic(\"test failed and t is missing `FailNow()`\")\n\t}\n\treturn false\n}\n\n// Fail reports a failure through\nfunc Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {\n\tif h, ok := t.(tHelper); ok {\n\t\th.Helper()\n\t}\n\tcontent := []labeledContent{\n\t\t{\"Error Trace\", strings.Join(CallerInfo(), \"\\n\\t\\t\\t\")},\n\t\t{\"Error\", failureMessage},\n\t}\n\n\t// Add test name if the Go version supports it\n\tif n, ok := t.(interface {\n\t\tName() string\n\t}); ok {","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/stretchr/testify/blob/001eb7946baf451879253643e4ce4b38eaa0d4a7/assert/assertions.go#L343-L379","documentation":"Panicked by FailNow (assert/assertions.go:346) when the passed TestingT does not implement the failNower interface (i.e. lacks a FailNow() method). The TestingT interface could not be extended with FailNow without breaking backwards compatibility (issue #263), so testify falls back to a panic. This typically surfaces when require-package assertions are used against a custom testing double that only implements Errorf/Logf.","triggerScenarios":"Passing a custom TestingT (e.g. a fake test reporter, a *bytes.Buffer wrapper, or a third-party test harness) to assert.FailNow or any require.* function, where that type implements Errorf but not FailNow. Also passing a plain *testing.TB value at the interface level in an older code path.","commonSituations":"Using require inside a custom assertion helper that accepts a minimal interface; wrapping *testing.T in a struct that forwards Errorf but forgets FailNow; using testify with a non-testing.T test runner (e.g. Ginkgo or a custom harness).","solutions":["Make your custom TestingT implement FailNow() (delegating to embedded *testing.T or calling runtime.Goexit).","Use assert.* (which only needs Errorf) instead of require.* when your fake lacks FailNow.","Embed *testing.T in your wrapper so it inherits FailNow for free."],"exampleFix":"// before\ntype myT struct{ log bytes.Buffer }\nfunc (m *myT) Errorf(f string, a ...any) { /* ... */ }\n// require.True(myT{}, x) -> panic\n// after\nfunc (m *myT) FailNow() { runtime.Goexit() }","handlingStrategy":"type-guard","validationCode":"func implementsFailNow(t assert.TestingT) bool {\n    _, ok := t.(interface{ FailNow() })\n    return ok\n}\n// before require.X: assert.True(t, implementsFailNow(tt))","typeGuard":"func hasFailNow(t assert.TestingT) bool {\n    _, ok := t.(interface{ FailNow() })\n    return ok\n}","tryCatchPattern":"// Either implement FailNow or fall back to assert.*:\nif !hasFailNow(tt) {\n    assert.True(tt, cond) // assert.* needs only Errorf\n} else {\n    require.True(tt, cond)\n}","preventionTips":["Always embed *testing.T in custom test doubles to inherit FailNow.","Prefer assert.* over require.* when the TestingT is a fake/minimal type.","Document the FailNow requirement on any helper accepting TestingT."],"tags":["testing-interface","panic","failnow","require","backwards-compat"],"analyzedSha":"001eb7946baf451879253643e4ce4b38eaa0d4a7","analyzedAt":"2026-08-04T21:49:58.715Z","schemaVersion":2}