gofr-dev/gofr · error

%w, got: %v

Error message

%w, got: %v

What it means

This is the wrapped form of errNegativeIdleConnTimeout from (*ConnectionPoolConfig).Validate, formatted with %w (errors.Is-compatible) and %v to include the offending time.Duration (e.g. "got: -5s"). It blocks applying an invalid keep-alive duration to the HTTP transport.

Source

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

	// IdleConnTimeout is the maximum amount of time an idle (keep-alive) connection will remain
	// idle before closing itself.
	// If not explicitly set (0), a default of 90 seconds will be used.
	// Negative values will cause validation error.
	IdleConnTimeout time.Duration
}

// Validate checks if the connection pool configuration values are valid.
func (c *ConnectionPoolConfig) Validate() error {
	if c.MaxIdleConns < 0 {
		return fmt.Errorf("%w, got: %d", errNegativeMaxIdleConns, c.MaxIdleConns)
	}

	if c.MaxIdleConnsPerHost < 0 {
		return fmt.Errorf("%w, got: %d", errNegativeMaxIdleConnsPerHost, c.MaxIdleConnsPerHost)
	}

	if c.IdleConnTimeout < 0 {
		return fmt.Errorf("%w, got: %v", errNegativeIdleConnTimeout, c.IdleConnTimeout)
	}

	return nil
}

// AddOption implements the Options interface to apply connection pool configuration to HTTP service.
// It modifies the underlying HTTP client's transport to use optimized connection pool settings.
func (c *ConnectionPoolConfig) AddOption(h HTTP) HTTP {
	// Extract the base httpService from any wrapped service
	httpSvc := extractHTTPService(h)
	if httpSvc == nil {
		// If we can't find the base service, return unchanged
		// This maintains backward compatibility
		return h
	}

	// Validate configuration before applying
	if err := c.Validate(); err != nil {

View on GitHub (pinned to 187eb24962)

Solutions

  1. Use 0 (default) or a positive duration for IdleConnTimeout; never negative
  2. Parse with time.ParseDuration and check sign immediately after loading config
  3. Clamp: if d < 0 { d = 0 } before building ConnectionPoolConfig
  4. Match with errors.Is(err, errNegativeIdleConnTimeout) for field-specific handling

Example fix

// before
pool := &ConnectionPoolConfig{IdleConnTimeout: timeout} // timeout = -30s from config
// after
timeout, _ := time.ParseDuration(cfg.IdleTimeout)
if timeout < 0 { timeout = 0 }
pool := &ConnectionPoolConfig{IdleConnTimeout: timeout}
Defensive patterns

Strategy: validation

Validate before calling

d, err := time.ParseDuration(cfg.IdleTimeout)
if err != nil { return err }
if d < 0 { return fmt.Errorf("IdleConnTimeout must be >= 0, got %v", d) }
pool := &ConnectionPoolConfig{IdleConnTimeout: d}

Type guard

func isNegativeIdleTimeoutErr(err error) bool { return errors.Is(err, errNegativeIdleConnTimeout) }

Try / catch

if err := pool.Validate(); err != nil {
    if isNegativeIdleTimeoutErr(err) {
        pool.IdleConnTimeout = 0 // fall back to transport default
    } else {
        return fmt.Errorf("connection pool config: %w", err)
    }
}

Prevention

When it happens

Trigger: Validate() (directly or via AddOption/AddHTTPService) encounters c.IdleConnTimeout < 0, e.g. ConnectionPoolConfig{IdleConnTimeout: -time.Minute}.Validate().

Common situations: Duration parsing mistakes (missing unit, sign typo) in config/env; using -1 as a sentinel for 'no timeout' which the library does not support; overflow in duration arithmetic.

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