{"id":"222dd4c632fe7670","repo":"gofiber/fiber","slug":"fiber-service-q-is-nil","errorCode":null,"errorMessage":"fiber: service %q is nil","messagePattern":"fiber: service %q is nil","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"services.go","lineNumber":124,"sourceCode":"\t\t}\n\n\t\terrs = append(errs, fmt.Errorf(\"service %s start: %w\", srv.String(), err))\n\t}\n\treturn errors.Join(errs...)\n}\n\n// shutdownServices Handles the shutdown process of services for the current application.\n// Iterates over all the started services in reverse order and tries to terminate them,\n// returning an error if any error occurs.\nfunc (app *App) shutdownServices(ctx context.Context) error {\n\tif app.state.ServicesLen() == 0 {\n\t\treturn nil\n\t}\n\n\tvar errs []error\n\tfor key, srv := range app.state.Services() {\n\t\tif srv == nil {\n\t\t\treturn fmt.Errorf(\"fiber: service %q is nil\", key)\n\t\t}\n\t\tif err := ctx.Err(); err != nil {\n\t\t\t// Context is canceled, do a best effort to terminate the services.\n\t\t\terrs = append(errs, fmt.Errorf(\"service %s terminate: %w\", srv.String(), err))\n\t\t\tcontinue\n\t\t}\n\n\t\terr := srv.Terminate(ctx)\n\t\tif err != nil {\n\t\t\t// Best effort to terminate the services.\n\t\t\terrs = append(errs, fmt.Errorf(\"service %s terminate: %w\", srv.String(), err))\n\t\t\tcontinue\n\t\t}\n\n\t\t// Remove the service from the State\n\t\tapp.state.deleteService(srv)\n\t}\n\treturn errors.Join(errs...)","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/services.go#L106-L142","documentation":"Returned by shutdownServices (services.go:124) when the app's internal state map contains a nil Service under a given key during termination. This is a defensive guard: app.state.setService only stores successfully-started services, so a nil entry indicates memory/state corruption or a bug in a custom Service whose Start mutated shared state.","triggerScenarios":"app.shutdownServices iterates app.state.Services() (services.go:122) and finds a nil value. Triggered during app.Shutdown after services were started. Requires the state map to have been populated with nil, which should not happen via normal APIs.","commonSituations":"Concurrent misuse of app state, a fork that injects nil into app.state.services, or a race between setService/deleteService during shutdown. In correct upstream usage this is effectively unreachable.","solutions":["Avoid touching app.state or app.configured.Services directly; use only fiber.Config.Services.","Ensure no goroutine sets app.state entries concurrently with Shutdown.","If forking, audit setService/deleteService to guarantee non-nil invariants.","Report as a Fiber bug if it reproduces on unmodified upstream with a minimal example."],"exampleFix":"// before: directly mutating app state (unsafe)\napp.state.setService(nil)\n\n// after: never inject nil; only registered services enter state\napp := fiber.New(fiber.Config{Services: []fiber.Service{realSvc}})","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never write nil into app.state directly.","Use only fiber.Config.Services to register services.","Treat occurrence as a bug; capture a goroutine dump and report upstream."],"tags":["services","shutdown","state","nil-check","invariant"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}