gofiber/fiber · critical

fiber: service at index %d is nil

Error message

fiber: service at index %d is nil

What it means

Returned by validateServicesSlice (services.go:40) when the config.Services slice passed to the Fiber app contains a nil entry. Fiber refuses to boot because a nil Service has no Start/Terminate methods and would panic later. The index in the message identifies exactly which slice position is nil.

Source

Thrown at services.go:40

	State(ctx context.Context) (string, error)

	// Terminate terminates the service, returning an error if it fails.
	Terminate(ctx context.Context) error
}

// hasConfiguredServices Checks if there are any services for the current application.
func (app *App) hasConfiguredServices() bool {
	return len(app.configured.Services) > 0
}

func (app *App) validateConfiguredServices() error {
	return validateServicesSlice(app.configured.Services)
}

func validateServicesSlice(services []Service) error {
	for idx, srv := range services {
		if srv == nil {
			return fmt.Errorf("fiber: service at index %d is nil", idx)
		}
	}
	return nil
}

// initServices If the app is configured to use services, this function registers
// a post shutdown hook to shutdown them after the server is closed.
// This function panics if there is an error starting the services.
func (app *App) initServices() {
	if !app.hasConfiguredServices() {
		return
	}

	if err := app.startServices(app.servicesStartupCtx()); err != nil {
		panic(err)
	}
}

View on GitHub (pinned to 9a4c7e57fe)

Solutions

  1. Filter nils out of the Services slice before passing it to fiber.New: only append non-nil services.
  2. Fix the service factory to never return nil; return an error instead and handle it.
  3. Use a guard helper: services = append(services, svc) only when svc != nil.

Example fix

// before
services := []fiber.Service{redisSvc, nil, metricsSvc}
app := fiber.New(fiber.Config{Services: services})

// after: build defensively
var services []fiber.Service
for _, s := range []fiber.Service{redisSvc, maybeMetricsSvc, metricsSvc} {
    if s != nil {
        services = append(services, s)
    }
}
app := fiber.New(fiber.Config{Services: services})
Defensive patterns

Strategy: validation

Validate before calling

services := []fiber.Service{a, b, c}
nonNil := services[:0]
for _, s := range services {
    if s != nil {
        nonNil = append(nonNil, s)
    }
}
app := fiber.New(fiber.Config{Services: nonNil})

Type guard

func isNonNilServices(s []fiber.Service) bool {
    for _, srv := range s {
        if srv == nil { return false }
    }
    return true
}

Prevention

When it happens

Trigger: Configuring app with fiber.Config{Services: []fiber.Service{someService, nil}} and then calling app.New() (validateConfiguredServices runs during construction). Also triggered by app.startServices in initServices.

Common situations: Conditional service registration that appends a nil when a flag is off (e.g. svc := maybeNewService(); Services: []Service{svc}), or a factory returning nil on partial failure. Refactoring that leaves a placeholder nil in a service list.

Related errors


AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04). Data as JSON: /data/errors/20873288e19964f4.json. Report an issue: GitHub.