Skip to content

go.bare_recover

Correctness High

Detects recover() calls that catch panics without logging or re-panicking, silently hiding errors.

Bare recover calls:

  • Hide bugs — Panics indicate serious problems that need attention
  • Lose context — No logs means no way to debug issues
  • Mask failures — Operations silently fail without notification
  • Delay fixes — Problems go unnoticed until they cascade
// ❌ Before (swallows panic)
func handler() {
defer func() {
recover() // Panic is silently ignored
}()
riskyOperation()
}
// ✅ After (logs and handles)
func handler() {
defer func() {
if r := recover(); r != nil {
log.Error("panic recovered",
"error", r,
"stack", string(debug.Stack()))
// Optionally re-panic or return error
}
}()
riskyOperation()
}
  • recover() without checking return value
  • recover() without logging
  • Naked defer recover() patterns
  • Silent panic suppression

Unfault generates patches that add proper panic handling:

defer func() {
if r := recover(); r != nil {
// Log with stack trace
log.Error("panic recovered",
"error", r,
"stack", string(debug.Stack()))
// Convert to error if possible
err = fmt.Errorf("panic: %v", r)
}
}()
// HTTP handler - prevent one bad request from crashing server
func panicMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if r := recover(); r != nil {
log.Error("HTTP handler panic", "path", r.URL.Path, "error", r)
http.Error(w, "Internal Server Error", 500)
}
}()
next.ServeHTTP(w, r)
})
}