stretchr/testify · error

cannot take func type as argument

Error message

cannot take func type as argument

What it means

Returned by validateEqualArgs (assert/assertions.go:518) when assert.Equal or assert.NotEqual is called with an argument whose reflect.Kind is reflect.Func. Functions are not comparable by reflect.DeepEqual in a meaningful identity sense, so testify rejects them outright to avoid producing misleading pass/fail results. The check is made via isFunction() (assert/assertions.go:1975) which inspects reflect.TypeOf(arg).Kind().

Source

Thrown at assert/assertions.go:524

		diff := diff(expected, actual)
		expected, actual = formatUnequalValues(expected, actual)
		return Fail(t, fmt.Sprintf("Not equal: \n"+
			"expected: %s\n"+
			"actual  : %s%s", expected, actual, diff), msgAndArgs...)
	}

	return true
}

// validateEqualArgs checks whether provided arguments can be safely used in the
// Equal/NotEqual functions.
func validateEqualArgs(expected, actual interface{}) error {
	if expected == nil && actual == nil {
		return nil
	}

	if isFunction(expected) || isFunction(actual) {
		return errors.New("cannot take func type as argument")
	}
	return nil
}

// Same asserts that two pointers reference the same object.
//
//	assert.Same(t, ptr1, ptr2)
//
// Both arguments must be pointer variables. Pointer variable sameness is
// determined based on the equality of both type and value.
func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
	if h, ok := t.(tHelper); ok {
		h.Helper()
	}

	same, ok := samePointers(expected, actual)
	if !ok {
		return Fail(t, "Both arguments must be pointers", msgAndArgs...)

View on GitHub (pinned to 001eb7946b)

Solutions

  1. Compare a non-comparable proxy instead of the func: compare the func's reflect.Pointer address, or assert on a captured return value.
  2. If you only care that both sides are non-nil funcs, use assert.NotNil on each side separately rather than Equal.
  3. If comparing func types (not values), use assert.IsType(t, (*func())(nil), actual) or mock.AnythingOfType("func()").

Example fix

// before
assert.Equal(t, handler.ServeHTTP, got)
// after
assert.NotNil(t, got)
Defensive patterns

Strategy: type-guard

Validate before calling

func isFuncArg(v interface{}) bool {
    if v == nil { return false }
    return reflect.TypeOf(v).Kind() == reflect.Func
}
// before assert.Equal: assert.False(t, isFuncArg(expected) || isFuncArg(actual))

Type guard

func isFuncValue(v interface{}) bool {
    if v == nil { return false }
    return reflect.TypeOf(v).Kind() == reflect.Func
}

Try / catch

// Go has no try/catch; validate before calling:
if isFuncValue(expected) || isFuncValue(actual) {
    t.Skip("cannot Equal func values")
}
assert.Equal(t, expected, actual)

Prevention

When it happens

Trigger: Calling assert.Equal(t, someFunc, otherFunc) or assert.NotEqual(t, fn, nil) where one side is a func value. Also triggered indirectly by assert.True/ObjectsAreEqualValues chains that route through Equal when a struct field happens to be a function type.

Common situations: Comparing handler/callback fields inside structs, asserting on http.HandlerFunc values, or passing a closure as an expected value by mistake instead of its return value. Common after refactors that turn a field from a value into a function.

Related errors


AI-assisted analysis of stretchr/testify@001eb7946b (2026-08-04). Data as JSON: /data/errors/1c5cc0bc48eed9a9.json. Report an issue: GitHub.