gofiber/fiber · warning
service terminate
Error message
service %s terminate: %w
What it means
Collected (not immediately returned) by shutdownServices() when ctx.Err() is non-nil at the top of an iteration. Because shutdown is best-effort, Fiber continues trying to terminate remaining services and appends this wrapped context error to the joined result rather than aborting.
Solutions
- Increase the shutdown context deadline via ServicesShutdownContextProvider.
- Make each service's Terminate() honor ctx and fail fast rather than blocking.
- Order services so dependents terminate before dependencies if the State ordering does not already.
- Profile Terminate() latency per service to find the slow one.
Example fix
// before — default background context, no deadline, tight server grace
app.Shutdown()
// a slow Terminate consumes time, later services see canceled ctx
// after — explicit generous shutdown context
app := fiber.New(fiber.Config{
ServicesShutdownContextProvider: func() context.Context {
ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
return ctx
},
})
app.Shutdown() Defensive patterns
Strategy: validation
Validate before calling
// Provide a generous shutdown context sized to total termination cost.
app := fiber.New(fiber.Config{
ServicesShutdownContextProvider: func() context.Context {
ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
return ctx
},
}) Try / catch
if err := app.Shutdown(); err != nil {
var joined interface{ Unwrap() []error }
if errors.As(err, &joined) {
for _, e := range joined.Unwrap() {
if errors.Is(e, context.Canceled) || errors.Is(e, context.DeadlineExceeded) {
log.Printf("shutdown truncated: %v", e)
}
}
}
} Prevention
- Make Terminate() honor ctx and fail fast.
- Size the shutdown deadline to the slowest service's termination cost.
- Drain in-flight work before returning from Terminate.
When it happens
Trigger: Shutdown context (from ServicesShutdownContextProvider) is canceled or expired while services are still being terminated. A long-running Terminate() on an earlier service consumed the deadline, leaving none for later ones.
Common situations: Shutdown deadline too tight for the service set; a service blocks in Terminate() (unclosed goroutines, hung network close); SIGTERM grace period shorter than total termination time.
Related errors
- context canceled while starting service
- service start
- fiber: service is nil
- timeout or cancel
- cache: failed to delete raw key
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/48358136d5f20aa6.
Report an issue: GitHub.
Appendix: source
Thrown at services.go:128
return errors.Join(errs...)
}
// shutdownServices Handles the shutdown process of services for the current application.
// Iterates over all the started services in reverse order and tries to terminate them,
// returning an error if any error occurs.
func (app *App) shutdownServices(ctx context.Context) error {
if app.state.ServicesLen() == 0 {
return nil
}
var errs []error
for key, srv := range app.state.Services() {
if srv == nil {
return fmt.Errorf("fiber: service %q is nil", key)
}
if err := ctx.Err(); err != nil {
// Context is canceled, do a best effort to terminate the services.
errs = append(errs, fmt.Errorf("service %s terminate: %w", srv.String(), err))
continue
}
err := srv.Terminate(ctx)
if err != nil {
// Best effort to terminate the services.
errs = append(errs, fmt.Errorf("service %s terminate: %w", srv.String(), err))
continue
}
// Remove the service from the State
app.state.deleteService(srv)
}
return errors.Join(errs...)
}
// logServices logs information about services and returns an error
// if any configured service is nil.View on GitHub (pinned to a105acad6c)