{"record":{"id":"adf0489b3db0c1b5","repo":"vitessio/vitess","slug":"setidletimeout-called-when-timer-not-initialized-adf048","errorCode":null,"errorMessage":"SetIdleTimeout called when timer not initialized","messagePattern":"SetIdleTimeout called when timer not initialized","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/pools/smartconnpool/benchmarking/legacy/resource_pool.go","lineNumber":503,"sourceCode":"\t\tclose(rp.resources)\n\t\tclose(rp.settingResources)\n\t}\n\treturn nil\n}\n\nfunc (rp *ResourcePool) recordWait(start time.Time) {\n\trp.waitCount.Add(1)\n\trp.waitTime.Add(time.Since(start).Nanoseconds())\n\tif rp.logWait != nil {\n\t\trp.logWait(start)\n\t}\n}\n\n// SetIdleTimeout sets the idle timeout. It can only be used if there was an\n// idle timeout set when the pool was created.\nfunc (rp *ResourcePool) SetIdleTimeout(idleTimeout time.Duration) {\n\tif rp.idleTimer == nil {\n\t\tpanic(\"SetIdleTimeout called when timer not initialized\")\n\t}\n\n\trp.idleTimeout.Store(idleTimeout.Nanoseconds())\n\trp.idleTimer.SetInterval(idleTimeout / 10)\n}\n\n// StatsJSON returns the stats in JSON format.\nfunc (rp *ResourcePool) StatsJSON() string {\n\treturn fmt.Sprintf(`{\"Capacity\": %v, \"Available\": %v, \"Active\": %v, \"InUse\": %v, \"MaxCapacity\": %v, \"WaitCount\": %v, \"WaitTime\": %v, \"IdleTimeout\": %v, \"IdleClosed\": %v, \"MaxLifetimeClosed\": %v, \"Exhausted\": %v}`,\n\t\trp.Capacity(),\n\t\trp.Available(),\n\t\trp.Active(),\n\t\trp.InUse(),\n\t\trp.MaxCap(),\n\t\trp.WaitCount(),\n\t\trp.WaitTime().Nanoseconds(),\n\t\trp.IdleTimeout().Nanoseconds(),\n\t\trp.IdleClosed(),","sourceCodeStart":485,"sourceCodeEnd":521,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/pools/smartconnpool/benchmarking/legacy/resource_pool.go#L485-L521","documentation":"ResourcePool.SetIdleTimeout panics if the pool was created without an idle timeout, because rp.idleTimer is nil in that case. The pool only spawns its periodic idle-reaping timer when a non-zero idle timeout was configured at construction, so SetIdleTimeout has nothing to reschedule. This is an intentional fail-fast for an API contract violation (doc: 'It can only be used if there was an idle timeout set when the pool was created').","triggerScenarios":"Calling rp.SetIdleTimeout(d) on a ResourcePool created via NewResourcePool with idleTimeout == 0 (or time.Duration(0)) so rp.idleTimer was never initialized.","commonSituations":"Config files where idle_timeout is unset/0 but code later tries to tune the idle timeout dynamically; refactors that moved SetIdleTimeout calls onto pools constructed with default (zero) settings.","solutions":["Set a non-zero idleTimeout when creating the ResourcePool (NewResourcePool ... idleTimeout), then call SetIdleTimeout at runtime","Guard the call: only invoke SetIdleTimeout if an idle timeout was configured at creation","If dynamic tuning without an initial timer is required, restructure to always start the idle timer (or recreate the pool) rather than calling SetIdleTimeout on a zero-configured pool"],"exampleFix":"// before\npool := NewResourcePool(factory, 10, 10, 0)\npool.SetIdleTimeout(30*time.Second) // panics\n// after\npool := NewResourcePool(factory, 10, 10, 30*time.Second)\npool.SetIdleTimeout(60*time.Second) // ok","handlingStrategy":"validation","validationCode":"if rp.idleTimeoutWasSet { // or track your own flag at construction\n    rp.SetIdleTimeout(d)\n}","typeGuard":"func canSetIdleTimeout(rp *ResourcePool) bool { return rp != nil /* pool created with non-zero idleTimeout */ }","tryCatchPattern":null,"preventionTips":["Always construct ResourcePool with a non-zero idleTimeout if you plan to tune it later","Wrap SetIdleTimeout behind a helper that tracks whether the pool supports it","Document in config that idle_timeout must be set for dynamic timeout changes"],"tags":["go","panic","resource-pool","connection-pool"],"backgroundTag":"pool-misconfiguration","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}