{"record":{"id":"f58686f3225baccb","repo":"gofiber/fiber","slug":"service-s-start-w","errorCode":null,"errorMessage":"service %s start: %w","messagePattern":"service (.+?) start: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"services.go","lineNumber":105,"sourceCode":"\tfor idx, srv := range app.configured.Services {\n\t\tif srv == nil {\n\t\t\treturn fmt.Errorf(\"fiber: service at index %d is nil\", idx)\n\t\t}\n\t\tif err := ctx.Err(); err != nil {\n\t\t\t// Context is canceled, return an error the soonest possible, so that\n\t\t\t// the user can see the context cancellation error and act on it.\n\t\t\treturn fmt.Errorf(\"context canceled while starting service %s: %w\", srv.String(), err)\n\t\t}\n\n\t\terr := srv.Start(ctx)\n\t\tif err == nil {\n\t\t\t// mark the service as started\n\t\t\tapp.state.setService(srv)\n\t\t\tcontinue\n\t\t}\n\n\t\tif errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {\n\t\t\treturn fmt.Errorf(\"service %s start: %w\", srv.String(), err)\n\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 {","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/services.go#L87-L123","documentation":"Returned by startServices() when srv.Start(ctx) itself returns an error that wraps context.Canceled or context.DeadlineExceeded (errors.Is matches). Unlike non-context errors which are collected and joined, a context error from Start causes an immediate return so the caller sees cancellation cleanly.","triggerScenarios":"A service's Start() respects the passed ctx and returns ctx.Err() (Canceled/DeadlineExceeded) when the startup context expires mid-start. The service correctly propagates cancellation and Fiber surfaces it without attempting remaining services.","commonSituations":"Service Start() blocks on a network/DB connect with the startup context; the deadline expires during that connect; SIGINT cancels the startup context; a dependency service is slow and pushes a later service past its own deadline.","solutions":["Increase the startup context deadline via ServicesStartupContextProvider.","Make the service's Start() use a per-service timeout shorter than the global one so it fails before the global deadline if it cannot connect.","Ensure infrastructure (DB, cache, message broker) is reachable with low latency from the process.","Defer heavy work (migration, warmup) to a background goroutine outside Start."],"exampleFix":"// before — Start blocks indefinitely on the global context\nfunc (s *DBSvc) Start(ctx context.Context) error {\n    db, err := sql.Open(\"postgres\", s.dsn) // no per-call timeout\n    return err\n}\n// global deadline expires -> service db start: context deadline exceeded\n\n// after — per-service connect timeout\nfunc (s *DBSvc) Start(ctx context.Context) error {\n    cctx, cancel := context.WithTimeout(ctx, 5*time.Second)\n    defer cancel()\n    db, err := sql.OpenDB(pgdriver.NewConnector(pgdriver.WithDSN(s.dsn)))\n    if err != nil { return err }\n    return db.PingContext(cctx)\n}","handlingStrategy":"try-catch","validationCode":"// Per-service connect timeout smaller than the global startup budget.\nfunc startWithTimeout(s fiber.Service, parent context.Context, d time.Duration) error {\n    ctx, cancel := context.WithTimeout(parent, d)\n    defer cancel()\n    return s.Start(ctx)\n}","typeGuard":null,"tryCatchPattern":"if err := app.Listen(\":3000\"); err != nil {\n    if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {\n        log.Printf(\"startup canceled: %v\", err)\n    }\n    log.Fatal(err)\n}","preventionTips":["Give each service a per-Start timeout below the global startup budget.","Defer heavy warmup out of Start into a background goroutine.","Verify dependency reachability before Listen."],"tags":["services","startup","context","deadline","cancellation"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}