gofr-dev/gofr · error
IdleConnTimeout cannot be negative
Error message
IdleConnTimeout cannot be negative
What it means
errNegativeIdleConnTimeout is a validation sentinel: ConnectionPoolConfig.Validate rejects a negative IdleConnTimeout because http.Transport cannot use a negative duration for how long idle connections are kept. Validate wraps it with the offending duration before returning.
Source
Thrown at pkg/gofr/service/connection_pool.go:13
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,
// },
// &service.CircuitBreakerConfig{...}, // Other options after ConnectionPoolConfigView on GitHub (pinned to 187eb24962)
Solutions
- Set IdleConnTimeout to zero (default behavior) or a positive duration like 90*time.Second
- If you meant 'disabled', use 0 rather than a negative duration
- Parse durations with time.ParseDuration and validate the sign at load time
- Use errors.Is(err, errNegativeIdleConnTimeout) to map the error back to the config field
Example fix
// before
pool := &ConnectionPoolConfig{IdleConnTimeout: -1 * time.Second} // meant 'no timeout'
// after
pool := &ConnectionPoolConfig{IdleConnTimeout: 0} // 0 = default; or 90 * time.Second Defensive patterns
Strategy: validation
Validate before calling
if pool.IdleConnTimeout < 0 {
return fmt.Errorf("IdleConnTimeout must be >= 0, got %v", pool.IdleConnTimeout)
}
if err := pool.Validate(); err != nil { return err } Type guard
func validTimeout(d time.Duration) bool { return d >= 0 } Try / catch
if err := pool.Validate(); err != nil {
if errors.Is(err, errNegativeIdleConnTimeout) {
pool.IdleConnTimeout = 0 // default behavior
} else {
return err
}
} Prevention
- Use 0, never a negative duration, to mean 'use default'
- Parse durations with time.ParseDuration and check the sign at load time
- Validate config before applying options to services
- Use errors.Is(err, errNegativeIdleConnTimeout) for precise handling
When it happens
Trigger: ConnectionPoolConfig{IdleConnTimeout: -time.Second} (any negative duration) passed to Validate() or applied through AddOption/AddHTTPService, which validates first.
Common situations: Parsing durations from config where a typo/missing unit or misparsed string becomes negative; intentionally using -1 to mean 'infinite' or 'disabled' (unsupported here); time.Duration arithmetic underflow.
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.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- MaxIdleConns cannot be negative
- MaxIdleConnsPerHost cannot be negative
- %w, got: %d
- %w, got: %v
- invalid FTP configuration: host and port are required
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/1aeed5a4ee4c7dd6.
Report an issue: GitHub.