Skip to content

🐛 bug: validate nil services early and during lifecycle#4050

Merged
ReneWerner87 merged 2 commits intomainfrom
add-validation-for-nil-service-entries
Feb 4, 2026
Merged

🐛 bug: validate nil services early and during lifecycle#4050
ReneWerner87 merged 2 commits intomainfrom
add-validation-for-nil-service-entries

Conversation

@gaby
Copy link
Member

@gaby gaby commented Feb 4, 2026

Motivation

  • Prevent panics and unclear errors when a configured Service is nil by validating entries before calling String() during startup, shutdown, and logging.
  • Surface configuration mistakes early during New(...) so apps fail-fast with a clear message instead of panicking inside lifecycle code.
  • Ensure startup logging does not call String() on nil services and that failures are surfaced to the startup message flow.

Description

  • Added validateConfiguredServices and helper validateServicesSlice to check for nil entries in Config.Services and invoked it during app initialization in New.
  • Added nil checks in startServices, shutdownServices, and logServices to return clear errors (including the service index or state key) before calling String() or other methods on services.
  • Changed logServices to return an error and updated the startup message flow in listen.go to log any error returned from logServices instead of ignoring it.
  • Updated tests in services_test.go to run in parallel, assert logServices returns no error, and added Test_NewConfiguredServicesNil to verify New panics with a clear error for nil service entries.

@gaby gaby requested a review from a team as a code owner February 4, 2026 12:33
Copilot AI review requested due to automatic review settings February 4, 2026 12:33
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 4, 2026

Walkthrough

Adds nil-service validation during app initialization and in service lifecycle routines. New validation causes New() to panic on invalid configured services; service start/shutdown/logging now return errors when encountering nil services, and startupMessage logs those errors.

Changes

Cohort / File(s) Summary
App init / validation
app.go
After copying config, calls validateConfiguredServices() and panics if it returns an error, adding early validation to startup.
Service lifecycle & logging
services.go, listen.go
Adds validateConfiguredServices() and validateServicesSlice(); startServices, shutdownServices, and logServices now check for nil services and return errors (logServices signature changed); startupMessage now logs logServices errors.
Tests
services_test.go
Updates Test_LogServices to assert no error from logServices; adds Test_NewConfiguredServicesNil to assert New(...) panics when configured services contain nil.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • sixcolors
  • ReneWerner87
  • efectn

Poem

🐰
I hopped through code at break of day,
I sniffed for nils and chased them away,
Now New() cries out if something's wrong,
Services sing tidy, error logs strong,
A carrot for tests — celebrate the play! 🥕

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description provides clear motivation, implementation details, and test updates, but does not follow the required template structure with sections like 'Changes introduced', 'Type of change', and 'Checklist'. Restructure the description to follow the repository template: add 'Changes introduced' section with checkboxes, select appropriate 'Type of change', complete the 'Checklist', and ensure all required sections are present.
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: validating nil services early and during lifecycle to prevent panics, matching the core objective of the PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add-validation-for-nil-service-entries

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @gaby, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a potential source of runtime panics and unclear errors by implementing robust validation for configured services. The changes ensure that nil service entries are caught early during application startup, leading to fail-fast behavior with clear error messages. Additionally, it hardens service lifecycle methods and logging against nil service references, improving overall application stability and diagnostic capabilities.

Highlights

  • Early Service Validation: Introduced validation during application initialization (New) to detect and panic early if nil services are configured, preventing runtime panics.
  • Runtime Nil Service Checks: Added explicit nil checks within startServices, shutdownServices, and logServices to prevent panics when interacting with potentially nil service entries during their lifecycle.
  • Improved Startup Logging Error Handling: Modified logServices to return an error, and updated the startup message flow in listen.go to properly log any errors encountered during service logging instead of silently ignoring them.
  • Enhanced Test Coverage: Updated services_test.go to run tests in parallel, assert that logServices returns no error, and added a new test case (Test_NewConfiguredServicesNil) to specifically verify the early panic for nil service configurations.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • app.go
    • Added a call to app.validateConfiguredServices() during New to panic if nil services are detected, ensuring early failure for misconfigurations.
  • listen.go
    • Modified app.startupMessage to check for and log any errors returned by app.logServices, improving error visibility during startup.
  • services.go
    • Introduced validateConfiguredServices and validateServicesSlice functions to systematically check for nil service entries.
    • Integrated nil checks into startServices and shutdownServices loops to prevent panics when iterating over services.
    • Changed the signature of logServices to return an error and added nil checks within its loop to handle invalid service states gracefully.
  • services_test.go
    • Enabled parallel execution for Test_LogServices.
    • Updated Test_LogServices to assert that app.logServices completes without returning an error.
    • Added Test_NewConfiguredServicesNil to verify that New panics with a specific error message when initialized with nil services.
Activity
  • Ran make audit, which failed due to govulncheck reporting known vulnerabilities in the Go standard library (11 vulnerabilities), but this is unrelated to the PR's changes.
  • Successfully ran make generate, make betteralign, make modernize, make format, and make lint with no issues.
  • Successfully ran make test, with all 2612 tests passing (1 skipped).
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@ReneWerner87 ReneWerner87 added this to v3 Feb 4, 2026
@ReneWerner87 ReneWerner87 added this to the v3 milestone Feb 4, 2026
@codecov
Copy link

codecov bot commented Feb 4, 2026

Codecov Report

❌ Patch coverage is 65.21739% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.10%. Comparing base (eec1258) to head (4b3e4fb).
⚠️ Report is 8 commits behind head on main.

Files with missing lines Patch % Lines
services.go 68.42% 3 Missing and 3 partials ⚠️
listen.go 0.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4050      +/-   ##
==========================================
- Coverage   91.21%   91.10%   -0.12%     
==========================================
  Files         119      119              
  Lines       11121    11138      +17     
==========================================
+ Hits        10144    10147       +3     
- Misses        620      629       +9     
- Partials      357      362       +5     
Flag Coverage Δ
unittests 91.10% <65.21%> (-0.12%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses a potential panic caused by nil services in the configuration by adding validation at various stages of the application lifecycle. The changes are logical and the inclusion of new tests is commendable. My feedback focuses on a couple of opportunities to reduce code duplication, which would enhance the maintainability of the new validation logic.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds validation to prevent nil services from causing panics during the application lifecycle. The changes ensure that configuration mistakes are caught early during app initialization and that defensive checks exist throughout the service lifecycle.

Changes:

  • Added early validation in New() to check for nil services in Config.Services and panic with a clear error message
  • Added defensive nil checks in startServices, shutdownServices, and logServices to prevent runtime panics
  • Changed logServices to return an error instead of failing silently, with proper error handling in the startup message flow

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
app.go Added validation call during app initialization to check for nil services
services.go Added validation functions and defensive nil checks throughout service lifecycle methods
listen.go Updated to handle error return from logServices with appropriate logging
services_test.go Added test for nil service validation, made Test_LogServices parallel, and added error assertion

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@services.go`:
- Around line 33-44: The nil check currently in validateServicesSlice (called by
App.validateConfiguredServices) only compares the interface to nil and misses
typed-nil service implementations; add a small helper isNilService(srv Service)
bool that first checks srv == nil and otherwise uses
reflect.ValueOf(srv).Kind()==reflect.Ptr && reflect.ValueOf(srv).IsNil() (or
more generally checks Value.IsValid/IsNil for pointer/interface kinds) to detect
typed-nil underlying values, then replace the plain nil checks in
validateServicesSlice and the other spots where services are
validated/started/shutdown/logged (places that call srv.Start(), srv.State(),
srv.Terminate(), srv.String(), etc.) to call isNilService(srv) and return an
error or skip accordingly so typed-nil services no longer cause panics.

Comment on lines +33 to +44
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
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's locate and examine the services.go file
find . -name "services.go" -type f | head -20

Repository: gofiber/fiber

Length of output: 70


🏁 Script executed:

# Get the actual content of services.go to verify the review's claims
head -250 services.go 2>/dev/null || find . -name "services.go" -exec head -250 {} \;

Repository: gofiber/fiber

Length of output: 5289


🏁 Script executed:

# Check if there's a gofiber/utils package and what nil-checking helpers exist
find . -path "*/gofiber/utils*" -type d | head -5
rg "isNil|nilService" --type go | head -20

Repository: gofiber/fiber

Length of output: 169


🏁 Script executed:

# Search for Service interface definition to understand the type
rg "type Service interface" -A 10 --type go

Repository: gofiber/fiber

Length of output: 569


🏁 Script executed:

# Check the isNilableKind implementation and its usage
rg "isNilableKind" -A 5 -B 2 --type go

Repository: gofiber/fiber

Length of output: 692


🏁 Script executed:

# Check imports in adapter.go to understand reflect usage pattern
grep -n "^import\|^[[:space:]]*\"" adapter.go | head -30

Repository: gofiber/fiber

Length of output: 185


🏁 Script executed:

# Search for all reflect.ValueOf usage in the codebase
rg "reflect.ValueOf|reflect.Kind" --type go | head -20

Repository: gofiber/fiber

Length of output: 1922


🏁 Script executed:

# Check if there are any examples of typed-nil services being created
rg "var.*Service.*nil|:=.*nil.*Service" --type go

Repository: gofiber/fiber

Length of output: 39


🏁 Script executed:

# Check if isNilableKind is exported (capital letter) or internal
rg "^func isNilableKind|^func IsNilableKind" -B 2 --type go

Repository: gofiber/fiber

Length of output: 137


🏁 Script executed:

# Check if there are any imports of functions from adapter.go
rg "from.*adapter|import.*adapter" --type go

Repository: gofiber/fiber

Length of output: 39


🏁 Script executed:

# Look at how services are constructed and passed - any evidence of typed-nil services?
rg "configured.Services\s*=" -B 5 -A 5 --type go | head -40

Repository: gofiber/fiber

Length of output: 39


🏁 Script executed:

# Check tests to see how services are tested
find . -name "*service*test*" -o -name "*test*service*" | head -10

Repository: gofiber/fiber

Length of output: 75


🏁 Script executed:

# Examine the services test file
cat -n services_test.go

Repository: gofiber/fiber

Length of output: 24114


🏁 Script executed:

# Check the config.go to see how services are configured
rg "Services.*\[\]Service" -B 3 -A 3 --type go

Repository: gofiber/fiber

Length of output: 6578


🏁 Script executed:

# Check if there's any pattern of creating typed-nil services in the codebase
rg "var\s+\w+\s*Service\s*=" --type go -A 1 | head -30

Repository: gofiber/fiber

Length of output: 39


🏁 Script executed:

# Check if the reflect package is already imported in services.go
head -20 services.go

Repository: gofiber/fiber

Length of output: 500


Nil-interface check misses typed‑nil services (panic still possible).

A Service can be a typed nil pointer; in that case srv == nil is false, but srv.Start()/String/State/Terminate will still panic. That defeats the goal of preventing nil-service panics. Consider a shared helper that detects nil underlying values and reuse it in validation/start/shutdown/log.

🛠️ Suggested fix: detect typed‑nil services once and reuse
@@
-import (
-	"context"
-	"errors"
-	"fmt"
-	"io"
-
-	"github.com/gofiber/utils/v2"
-)
+import (
+	"context"
+	"errors"
+	"fmt"
+	"io"
+	"reflect"
+
+	"github.com/gofiber/utils/v2"
+)
@@
-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
-}
+func validateServicesSlice(services []Service) error {
+	for idx, srv := range services {
+		if isNilService(srv) {
+			return fmt.Errorf("fiber: service at index %d is nil", idx)
+		}
+	}
+	return nil
+}
+
+func isNilService(srv Service) bool {
+	if srv == nil {
+		return true
+	}
+	v := reflect.ValueOf(srv)
+	switch v.Kind() {
+	case reflect.Pointer, reflect.Map, reflect.Slice, reflect.Func, reflect.Interface, reflect.Chan:
+		return v.IsNil()
+	default:
+		return false
+	}
+}
@@
-	for idx, srv := range app.configured.Services {
-		if srv == nil {
+	for idx, srv := range app.configured.Services {
+		if isNilService(srv) {
@@
-	for key, srv := range app.state.Services() {
-		if srv == nil {
+	for key, srv := range app.state.Services() {
+		if isNilService(srv) {
@@
-	for key, srv := range app.state.Services() {
-		if srv == nil {
+	for key, srv := range app.state.Services() {
+		if isNilService(srv) {

Also applies to: 87-90, 122-125, 146-176

🤖 Prompt for AI Agents
In `@services.go` around lines 33 - 44, The nil check currently in
validateServicesSlice (called by App.validateConfiguredServices) only compares
the interface to nil and misses typed-nil service implementations; add a small
helper isNilService(srv Service) bool that first checks srv == nil and otherwise
uses reflect.ValueOf(srv).Kind()==reflect.Ptr && reflect.ValueOf(srv).IsNil()
(or more generally checks Value.IsValid/IsNil for pointer/interface kinds) to
detect typed-nil underlying values, then replace the plain nil checks in
validateServicesSlice and the other spots where services are
validated/started/shutdown/logged (places that call srv.Start(), srv.State(),
srv.Terminate(), srv.String(), etc.) to call isNilService(srv) and return an
error or skip accordingly so typed-nil services no longer cause panics.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@ReneWerner87 ReneWerner87 merged commit eff8808 into main Feb 4, 2026
17 of 21 checks passed
@ReneWerner87 ReneWerner87 deleted the add-validation-for-nil-service-entries branch February 4, 2026 16:12
@github-project-automation github-project-automation bot moved this to Done in v3 Feb 4, 2026
@ReneWerner87 ReneWerner87 modified the milestones: v3, v3.1.0 Feb 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants