hibiken/asynq · critical
asynq: nil handler
Error message
asynq: nil handler
What it means
ServeMux.Handle panics with "asynq: nil handler" when the handler argument passed to Handle is nil. A registration without a concrete Handler implementation cannot dispatch tasks, so the mux rejects it immediately at registration time with a panic.
Solutions
- Ensure a non-nil Handler (or HandlerFunc) is passed for every registration
- Check factory/lookup functions so they never return nil handlers silently
- Guard the call: if h == nil { log.Fatal("missing handler for pattern") } before mux.Handle
- When wrapping handlers in middleware, verify the wrapped chain is non-nil
Example fix
// before
mux.Handle(pattern, handlers[pattern]) // may be nil
// after
if h := handlers[pattern]; h != nil {
mux.Handle(pattern, h)
} else {
log.Fatalf("no handler registered for %q", pattern)
} Defensive patterns
Strategy: validation
Validate before calling
if handler == nil {
return errors.New("cannot register nil handler for pattern " + pattern)
}
mux.Handle(pattern, handler) Type guard
func hasHandler(h asynq.Handler) bool { return h != nil } Prevention
- Ensure handler factories never return (nil, nil); always return an error when no handler can be built
- Audit registration tables/maps for nil entries before wiring
- Wrap middlewares so the outermost value is always a non-nil HandlerFunc
- Add a startup assertion that every expected task type maps to a non-nil handler
When it happens
Trigger: Calling mux.Handle("task:name", nil); passing a nil Handler-typed variable (a nil *MyHandler stored in a Handler interface is caught only if the interface value itself is nil); wiring handlers from a map/slice that has a nil entry.
Common situations: Handler factories returning nil on some config path; slices of handlers built conditionally leaving nil slots; type-asserting an interface to Handler where the assertion succeeded but the value was nil.
Related errors
- asynq: invalid pattern
- asynq: multiple registrations for
- asynq: unsupported RedisConnOpt type %T
- inspeq: unsupported RedisConnOpt type %T
- asynq: cannot start uninitialized PeriodicTaskManager; use…
AI-assisted analysis of hibiken/asynq@d135f1439b (2026-09-07).
Data as JSON: /api/errors/110834214442a8d0.
Report an issue: GitHub.
Appendix: source
Thrown at servemux.go:109
if strings.HasPrefix(typename, e.pattern) {
return e.h, e.pattern
}
}
return nil, ""
}
// Handle registers the handler for the given pattern.
// If a handler already exists for pattern, Handle panics.
func (mux *ServeMux) Handle(pattern string, handler Handler) {
mux.mu.Lock()
defer mux.mu.Unlock()
if strings.TrimSpace(pattern) == "" {
panic("asynq: invalid pattern")
}
if handler == nil {
panic("asynq: nil handler")
}
if _, exist := mux.m[pattern]; exist {
panic("asynq: multiple registrations for " + pattern)
}
if mux.m == nil {
mux.m = make(map[string]muxEntry)
}
e := muxEntry{h: handler, pattern: pattern}
mux.m[pattern] = e
mux.es = appendSorted(mux.es, e)
}
func appendSorted(es []muxEntry, e muxEntry) []muxEntry {
n := len(es)
i := sort.Search(n, func(i int) bool {
return len(es[i].pattern) < len(e.pattern)
})View on GitHub (pinned to d135f1439b)