gofiber/fiber · error

fiber: Config.RegexHandler must be a non-nil function

Error message

fiber: Config.RegexHandler must be a non-nil function

What it means

Panics from constraint.go:58 inside validateRegexHandler when RegexHandler is a non-nil value that is either not a function (Kind != Func) or is a nil function value (handlerValue.IsNil()). A nil interface is fine - it defaults to regexp.MustCompile; only a typed-but-nil or non-function value is rejected. Validation runs at app construction (app.go:791) and on every parseRoute call.

Source

Thrown at constraint.go:58

	result := reflect.ValueOf(handler).Call([]reflect.Value{reflect.ValueOf(pattern)})
	matcher, ok := result[0].Interface().(regexMatcher)
	if !ok {
		panic("fiber: Config.RegexHandler return type must support MatchString(string) bool")
	}
	if isNilRegexMatcher(matcher) {
		panic("fiber: Config.RegexHandler must not return nil")
	}
	return matcher
}

func validateRegexHandler(handler any) any {
	if handler == nil {
		return regexp.MustCompile
	}
	handlerValue := reflect.ValueOf(handler)
	handlerType := handlerValue.Type()
	if handlerType.Kind() != reflect.Func || handlerValue.IsNil() {
		panic("fiber: Config.RegexHandler must be a non-nil function")
	}
	if handlerType.NumIn() != 1 || handlerType.In(0) != stringType || handlerType.NumOut() != 1 {
		panic("fiber: Config.RegexHandler must have signature func(string) T")
	}
	if !handlerType.Out(0).Implements(regexMatcherType) {
		panic("fiber: Config.RegexHandler return type must support MatchString(string) bool")
	}
	return handler
}

// ConstraintHandler is the interface that all constraints must implement.
// Built-in and custom constraints are treated uniformly through this interface.
type ConstraintHandler interface {
	// Name returns the constraint identifier used in route patterns (e.g. "int", "minLen", "regex").
	Name() string

	// Execute validates a request parameter value against the constraint.
	// param is the request parameter value to check.

View on GitHub (pinned to 9a4c7e57fe)

Solutions

  1. Pass the compiler function reference, not a value: RegexHandler: regexp.MustCompile (no parentheses, no argument).
  2. Leave RegexHandler unset/nil to accept the regexp.MustCompile default.
  3. If injecting from config, type-check at load time and fall back to the default when the value is not a function.

Example fix

// before
var compile func(string) *regexp.Regexp // declared, never set
app := fiber.New(fiber.Config{RegexHandler: compile})

// after
app := fiber.New() // defaults to regexp.MustCompile
// or, explicitly:
app := fiber.New(fiber.Config{RegexHandler: regexp.MustCompile})
Defensive patterns

Strategy: type-guard

Type guard

func isValidRegexHandler(h any) bool {
    if h == nil {
        return true // defaults to regexp.MustCompile
    }
    hv := reflect.ValueOf(h)
    if hv.Kind() != reflect.Func || hv.IsNil() {
        return false
    }
    return true
}

Prevention

When it happens

Trigger: New(Config{RegexHandler: "invalid"}) (a string), New(Config{RegexHandler: 42}) (an int), or passing a nil function variable: var f func(string) *regexp.Regexp; New(Config{RegexHandler: f}).

Common situations: Assigning the compiled regexp object instead of the compiler function (RegexHandler: regexp.MustCompile(`\d+`) instead of regexp.MustCompile); typo where a field name is reused for a different type; DI injecting the wrong value.

Related errors


AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04). Data as JSON: /data/errors/c42266f78329c90c.json. Report an issue: GitHub.