{"record":{"id":"8ad8b9b2d3156e8b","repo":"router-for-me/CLIProxyAPI","slug":"credential-concurrency-lifecycle-timing-safety-inv","errorCode":null,"errorMessage":"credential concurrency lifecycle timing safety invariant overflows","messagePattern":"credential concurrency lifecycle timing safety invariant overflows","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/credential_concurrency.go","lineNumber":181,"sourceCode":"\t}\n\tif cfg.MaxLimit < 1 || cfg.MaxLimit > maxCredentialConcurrencyLimit {\n\t\treturn fmt.Errorf(\"credential concurrency max limit must be between 1 and %d\", maxCredentialConcurrencyLimit)\n\t}\n\treturn nil\n}\n\n// ValidateCredentialConcurrencyLifecycle verifies the Home lifecycle timing safety invariant.\nfunc ValidateCredentialConcurrencyLifecycle(nodeHeartbeatTimeout time.Duration, cfg CredentialConcurrencyConfig) error {\n\tif nodeHeartbeatTimeout <= 0 {\n\t\treturn fmt.Errorf(\"credential concurrency lifecycle durations must be positive\")\n\t}\n\tif errValidate := ValidateCredentialConcurrency(cfg); errValidate != nil {\n\t\treturn errValidate\n\t}\n\tleft, leftOverflow := addCredentialConcurrencyDuration(nodeHeartbeatTimeout, cfg.ReclaimGrace)\n\tright, rightOverflow := addCredentialConcurrencyDuration(cfg.CPAHeartbeatTimeout, cfg.CPACancelBound)\n\tif leftOverflow || rightOverflow {\n\t\treturn fmt.Errorf(\"credential concurrency lifecycle timing safety invariant overflows\")\n\t}\n\tif left <= right {\n\t\treturn fmt.Errorf(\"node heartbeat timeout plus reclaim grace must exceed CPA heartbeat timeout plus cancel bound\")\n\t}\n\treturn nil\n}\n\nfunc addCredentialConcurrencyDuration(left time.Duration, right time.Duration) (time.Duration, bool) {\n\tif right > 0 && left > time.Duration(1<<63-1)-right {\n\t\treturn 0, true\n\t}\n\treturn left + right, false\n}\n","sourceCodeStart":163,"sourceCodeEnd":195,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/config/credential_concurrency.go#L163-L195","documentation":"ValidateCredentialConcurrencyLifecycle sums nodeHeartbeatTimeout+reclaim-grace and cpa-heartbeat-timeout+cpa-cancel-bound using a checked addition; if either sum would overflow int64 nanoseconds (max ~292 years), the check reports an overflow instead of silently wrapping. Only reachable with absurdly huge duration values in config.","triggerScenarios":"credential-concurrency durations near time.Duration max, e.g. 'cpa-heartbeat-timeout: 2562047h' combined with a large cpa-cancel-bound, or any pair whose nanosecond sum exceeds 1<<63-1.","commonSituations":"Config generation bugs emitting huge numbers (e.g. milliseconds passed where nanoseconds expected via integer cast); copy-paste of a duration with too many zeros; effectively never seen with human-written values.","solutions":["Bring all credential-concurrency durations back to sane magnitudes (seconds to minutes).","If generating configs programmatically, verify unit conversions (time.Duration is nanoseconds; use time.Second multipliers).","Re-validate after scaling down."],"exampleFix":"# before (config.yaml)\ncredential-concurrency:\n  cpa-heartbeat-timeout: 2562047h\n  cpa-cancel-bound: 2562047h\n\n# after\ncredential-concurrency:\n  cpa-heartbeat-timeout: 3s\n  cpa-cancel-bound: 5s","handlingStrategy":"validation","validationCode":"// Go: sanity-cap durations before validation.\nfunc saneDuration(d time.Duration) bool { return d > 0 && d < 24*time.Hour }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep credential-concurrency durations in the seconds-to-minutes range.","In code, build durations with time.Second multipliers, never raw int64 nanosecond casts."],"tags":["config","validation","credential-concurrency","overflow","durations"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}