{"record":{"id":"110834214442a8d0","repo":"hibiken/asynq","slug":"asynq-nil-handler","errorCode":null,"errorMessage":"asynq: nil handler","messagePattern":"asynq: nil handler","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"servemux.go","lineNumber":109,"sourceCode":"\t\tif strings.HasPrefix(typename, e.pattern) {\n\t\t\treturn e.h, e.pattern\n\t\t}\n\t}\n\treturn nil, \"\"\n\n}\n\n// Handle registers the handler for the given pattern.\n// If a handler already exists for pattern, Handle panics.\nfunc (mux *ServeMux) Handle(pattern string, handler Handler) {\n\tmux.mu.Lock()\n\tdefer mux.mu.Unlock()\n\n\tif strings.TrimSpace(pattern) == \"\" {\n\t\tpanic(\"asynq: invalid pattern\")\n\t}\n\tif handler == nil {\n\t\tpanic(\"asynq: nil handler\")\n\t}\n\tif _, exist := mux.m[pattern]; exist {\n\t\tpanic(\"asynq: multiple registrations for \" + pattern)\n\t}\n\n\tif mux.m == nil {\n\t\tmux.m = make(map[string]muxEntry)\n\t}\n\te := muxEntry{h: handler, pattern: pattern}\n\tmux.m[pattern] = e\n\tmux.es = appendSorted(mux.es, e)\n}\n\nfunc appendSorted(es []muxEntry, e muxEntry) []muxEntry {\n\tn := len(es)\n\ti := sort.Search(n, func(i int) bool {\n\t\treturn len(es[i].pattern) < len(e.pattern)\n\t})","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/hibiken/asynq/blob/d135f1439bee74e989b7f9b41ecd542cc87f024a/servemux.go#L91-L127","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nmux.Handle(pattern, handlers[pattern]) // may be nil\n\n// after\nif h := handlers[pattern]; h != nil {\n    mux.Handle(pattern, h)\n} else {\n    log.Fatalf(\"no handler registered for %q\", pattern)\n}","handlingStrategy":"validation","validationCode":"if handler == nil {\n    return errors.New(\"cannot register nil handler for pattern \" + pattern)\n}\nmux.Handle(pattern, handler)","typeGuard":"func hasHandler(h asynq.Handler) bool { return h != nil }","tryCatchPattern":null,"preventionTips":["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"],"tags":["panic","routing","nil","go"],"backgroundTag":"null-argument","analyzedSha":"d135f1439bee74e989b7f9b41ecd542cc87f024a","analyzedAt":"2026-09-07T19:02:34.660Z","contentChangedAt":"2026-09-07T19:02:34.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}