{"id":"025e8f33c9fd9f0b","repo":"gofiber/fiber","slug":"runtime-goexit-called-in-handler-or-server-panic","errorCode":null,"errorMessage":"runtime.Goexit() called in handler or server panic","messagePattern":"runtime\\.Goexit\\(\\) called in handler or server panic","errorType":"exception","errorClass":"ErrHandlerExited","httpStatus":null,"severity":"error","filePath":"error.go","lineNumber":20,"sourceCode":"\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\n\t\"github.com/gofiber/schema\"\n)\n\n// Wrap and return this for unreachable code if panicking is undesirable (i.e., in a handler).\n// Unexported because users will hopefully never need to see it.\nvar errUnreachable = errors.New(\"fiber: unreachable code, please create an issue at github.com/gofiber/fiber\")\n\n// General errors\nvar (\n\tErrGracefulTimeout = errors.New(\"shutdown: graceful timeout has been reached, exiting\")\n\t// ErrNotRunning indicates that a Shutdown method was called when the server was not running.\n\tErrNotRunning = errors.New(\"shutdown: server is not running\")\n\t// ErrHandlerExited is returned by App.Test if a handler panics or calls runtime.Goexit().\n\tErrHandlerExited = errors.New(\"runtime.Goexit() called in handler or server panic\")\n\t// ErrNoViewEngineConfigured indicates that a helper requiring a view engine was invoked without one configured.\n\tErrNoViewEngineConfigured = errors.New(\"fiber: no view engine configured\")\n\t// ErrAutoCertWithCertFile indicates AutoCertManager cannot be used with CertFile/CertKeyFile.\n\tErrAutoCertWithCertFile = errors.New(\"tls: AutoCertManager cannot be combined with CertFile/CertKeyFile\")\n)\n\n// Fiber redirection errors\nvar (\n\tErrRedirectBackNoFallback = NewError(StatusInternalServerError, \"Referer not found, you have to enter fallback URL for redirection.\")\n)\n\n// Range errors\nvar (\n\t// ErrRangeMalformed is returned for a syntactically invalid Range header,\n\t// which RFC 9110 Section 14.2 allows a server to reject; it carries a\n\t// 400 Bad Request status so propagating it does not surface as a 500.\n\tErrRangeMalformed = NewError(StatusBadRequest, \"range: malformed range header string\")\n\t// ErrRangeUnsupported is returned for a Range header whose range unit is","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/error.go#L2-L38","documentation":"ErrHandlerExited (error.go:20) is returned by App.Test (app.go:1442) when the goroutine serving the test connection returns abnormally because a handler called runtime.Goexit() or panicked in a way that unwound the stack without producing a normal ServeConn result. It distinguishes a 'the handler bailed out' condition from a real HTTP/network error so test authors know to inspect handler code rather than the test plumbing.","triggerScenarios":"Inside app.Test(...), a handler calls runtime.Goexit(), or a panic occurs that is not recovered by Fiber's recovery middleware, causing the deferred channel send at app.go:1442 to fire. Test helpers that spawn goroutines which call runtime.Goexit() also trigger it.","commonSituations":"Handler code imported from a library that uses runtime.Goexit() on validation failure, a panic that bypasses recovery (e.g. in a goroutine spawned by the handler), or test setup that nils the recovery middleware.","solutions":["Audit the handler under test for runtime.Goexit() calls and replace them with returned errors.","Ensure fiber.Config or the recovery middleware is active so panics are recovered rather than unwinding the test goroutine.","Reproduce the panic directly (without app.Test) to read the stack trace and fix the root cause."],"exampleFix":"// before\napp.Get(\"/exit\", func(c fiber.Ctx) error {\n    if bad {\n        runtime.Goexit() // produces ErrHandlerExited in app.Test\n    }\n    return c.SendStatus(200)\n})\n\n// after\napp.Get(\"/exit\", func(c fiber.Ctx) error {\n    if bad {\n        return fiber.NewError(fiber.StatusBadRequest, \"bad input\")\n    }\n    return c.SendStatus(200)\n})","handlingStrategy":"try-catch","validationCode":"// Enable recovery so panics in handlers don't unwind the test goroutine.\napp := fiber.New(fiber.Config{DisableDefaultErrorHandler: false})\napp.Use(recoverware.New())","typeGuard":null,"tryCatchPattern":"resp, err := app.Test(req)\nif errors.Is(err, fiber.ErrHandlerExited) {\n    t.Fatal(\"handler panicked or called runtime.Goexit; check handler code\")\n}","preventionTips":["Never call runtime.Goexit() inside a handler; return an error instead.","Always run the recover middleware so panics are contained.","Reproduce panics outside app.Test to read the full stack trace."],"tags":["testing","handler","panic","lifecycle","fiber"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}