{"record":{"id":"1aeed5a4ee4c7dd6","repo":"gofr-dev/gofr","slug":"idleconntimeout-cannot-be-negative","errorCode":null,"errorMessage":"IdleConnTimeout cannot be negative","messagePattern":"IdleConnTimeout cannot be negative","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/service/connection_pool.go","lineNumber":13,"sourceCode":"package service\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n)\n\nvar (\n\terrNegativeMaxIdleConns        = errors.New(\"MaxIdleConns cannot be negative\")\n\terrNegativeMaxIdleConnsPerHost = errors.New(\"MaxIdleConnsPerHost cannot be negative\")\n\terrNegativeIdleConnTimeout     = errors.New(\"IdleConnTimeout cannot be negative\")\n)\n\n// ConnectionPoolConfig holds the configuration for HTTP connection pool settings.\n// It customizes the HTTP transport layer to optimize connection reuse for high-frequency requests.\n//\n// Note: This configuration must be applied first when using multiple options with AddHTTPService,\n// as it needs to access the underlying HTTP client transport. If applied after wrapper options\n// (CircuitBreaker, Retry, OAuth), it will be silently ignored.\n//\n// Example:\n//\n//\tapp.AddHTTPService(\"api-service\", \"https://api.example.com\",\n//\t    &service.ConnectionPoolConfig{\n//\t        MaxIdleConns:        100,\n//\t        MaxIdleConnsPerHost: 20,\n//\t        IdleConnTimeout:     90 * time.Second,\n//\t    },\n//\t    &service.CircuitBreakerConfig{...}, // Other options after ConnectionPoolConfig","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/service/connection_pool.go#L1-L31","documentation":"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.","triggerScenarios":"ConnectionPoolConfig{IdleConnTimeout: -time.Second} (any negative duration) passed to Validate() or applied through AddOption/AddHTTPService, which validates first.","commonSituations":"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.","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"],"exampleFix":"// before\npool := &ConnectionPoolConfig{IdleConnTimeout: -1 * time.Second} // meant 'no timeout'\n// after\npool := &ConnectionPoolConfig{IdleConnTimeout: 0} // 0 = default; or 90 * time.Second","handlingStrategy":"validation","validationCode":"if pool.IdleConnTimeout < 0 {\n    return fmt.Errorf(\"IdleConnTimeout must be >= 0, got %v\", pool.IdleConnTimeout)\n}\nif err := pool.Validate(); err != nil { return err }","typeGuard":"func validTimeout(d time.Duration) bool { return d >= 0 }","tryCatchPattern":"if err := pool.Validate(); err != nil {\n    if errors.Is(err, errNegativeIdleConnTimeout) {\n        pool.IdleConnTimeout = 0 // default behavior\n    } else {\n        return err\n    }\n}","preventionTips":["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"],"tags":["http-client","configuration","connection-pool","validation"],"backgroundTag":"invalid-config-value","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}