gofr-dev/gofr · error

MaxIdleConns cannot be negative

Error message

MaxIdleConns cannot be negative

What it means

errNegativeMaxIdleConns is a validation sentinel: ConnectionPoolConfig.Validate rejects a negative MaxIdleConns because net/http's Transport cannot accept a negative idle-connection pool size. It's wrapped with the offending value by Validate and returned when adding connection-pool options to an HTTP service.

Source

Thrown at pkg/gofr/service/connection_pool.go:11

package service

import (
	"errors"
	"fmt"
	"net/http"
	"time"
)

var (
	errNegativeMaxIdleConns        = errors.New("MaxIdleConns cannot be negative")
	errNegativeMaxIdleConnsPerHost = errors.New("MaxIdleConnsPerHost cannot be negative")
	errNegativeIdleConnTimeout     = errors.New("IdleConnTimeout cannot be negative")
)

// ConnectionPoolConfig holds the configuration for HTTP connection pool settings.
// It customizes the HTTP transport layer to optimize connection reuse for high-frequency requests.
//
// Note: This configuration must be applied first when using multiple options with AddHTTPService,
// as it needs to access the underlying HTTP client transport. If applied after wrapper options
// (CircuitBreaker, Retry, OAuth), it will be silently ignored.
//
// Example:
//
//	app.AddHTTPService("api-service", "https://api.example.com",
//	    &service.ConnectionPoolConfig{
//	        MaxIdleConns:        100,
//	        MaxIdleConnsPerHost: 20,
//	        IdleConnTimeout:     90 * time.Second,

View on GitHub (pinned to 187eb24962)

Solutions

  1. Fix the config source so MaxIdleConns is >= 0 (0 is valid and means default)
  2. Clamp before validation: if v < 0 { v = 0 } or use math.Max(0, v)
  3. Validate configuration at startup so a bad env value fails fast with a clear message
  4. Use errors.Is(err, errNegativeMaxIdleConns) to report which field is invalid in config loaders

Example fix

// before
pool := &ConnectionPoolConfig{MaxIdleConns: -1}
// after
maxIdle := envInt("MAX_IDLE_CONNS", 100)
if maxIdle < 0 { maxIdle = 0 }
pool := &ConnectionPoolConfig{MaxIdleConns: maxIdle}
Defensive patterns

Strategy: validation

Validate before calling

if pool.MaxIdleConns < 0 {
    return fmt.Errorf("MaxIdleConns must be >= 0, got %d", pool.MaxIdleConns)
}
if err := pool.Validate(); err != nil { return err }

Type guard

func (c *ConnectionPoolConfig) IsSane() bool {
    return c.MaxIdleConns >= 0 && c.MaxIdleConnsPerHost >= 0 && c.IdleConnTimeout >= 0
}

Try / catch

if err := pool.Validate(); err != nil {
    if errors.Is(err, errNegativeMaxIdleConns) {
        pool.MaxIdleConns = 0 // fall back to default and retry once
    } else {
        return err
    }
}

Prevention

When it happens

Trigger: Constructing ConnectionPoolConfig{MaxIdleConns: -1} (or any negative) and calling Validate() directly, or passing it via AddOption/AddHTTPService which invokes Validate before applying the transport settings.

Common situations: Computing pool sizes from environment/config where an unset or misparsed variable becomes negative; subtracting in size math (e.g. total - reserved) yielding negative; copy-paste sign errors in defaults.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01). Data as JSON: /api/errors/38360452d300f7b1. Report an issue: GitHub.