gofr-dev/gofr · error

MaxIdleConnsPerHost cannot be negative

Error message

MaxIdleConnsPerHost cannot be negative

What it means

errNegativeMaxIdleConnsPerHost is a validation sentinel: ConnectionPoolConfig.Validate rejects a negative MaxIdleConnsPerHost because http.Transport requires a non-negative per-host idle connection limit. Validate wraps it with the offending value before returning.

Source

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

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. Set MaxIdleConnsPerHost to a non-negative value in the config source
  2. Clamp negative computed values to 0 before constructing ConnectionPoolConfig
  3. Fail fast at startup by calling Validate() immediately after loading config
  4. Match with errors.Is(err, errNegativeMaxIdleConnsPerHost) in config error handling to pinpoint the field

Example fix

// before
pool := &ConnectionPoolConfig{MaxIdleConnsPerHost: total / hosts} // can be negative
// after
perHost := total / max(hosts, 1)
if perHost < 0 { perHost = 0 }
pool := &ConnectionPoolConfig{MaxIdleConnsPerHost: perHost}
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

func validPerHost(v int) bool { return v >= 0 }

Try / catch

if err := pool.Validate(); err != nil {
    if errors.Is(err, errNegativeMaxIdleConnsPerHost) {
        pool.MaxIdleConnsPerHost = 2 // sane default
    } else {
        return err
    }
}

Prevention

When it happens

Trigger: ConnectionPoolConfig{MaxIdleConnsPerHost: -1} passed to Validate(), or added to a service via AddOption/AddHTTPService which runs Validate first.

Common situations: Formula-derived per-host values (e.g. dividing totals) going negative on empty inputs; YAML/JSON config with negative numbers; misunderstanding that 0 is allowed (it means default/1) while negatives are not.

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/3b27b52050e45880. Report an issue: GitHub.