{"record":{"id":"3800490bcac5bd08","repo":"temporalio/temporal","slug":"internal-error-call-to-retrylockedsource-seed","errorCode":null,"errorMessage":"internal error: call to RetryLockedSource.Seed","messagePattern":"internal error: call to RetryLockedSource\\.Seed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/backoff/retrypolicy.go","lineNumber":339,"sourceCode":"// See the following discussions for details\n// https://github.com/golang/go/issues/24121 <- main\n// https://github.com/stripe/veneur/pull/466 -< make rng source faster\n// https://github.com/golang/go/issues/25057\n// https://github.com/golang/go/issues/21393\n\ntype RetryLockedSource struct {\n\tlk sync.Mutex\n\ts  rand.Source\n}\n\nfunc (r *RetryLockedSource) Int63() int64 {\n\tr.lk.Lock()\n\tdefer r.lk.Unlock()\n\treturn r.s.Int63()\n}\n\nfunc (r *RetryLockedSource) Seed(seed int64) {\n\tpanic(\"internal error: call to RetryLockedSource.Seed\")\n}\n\nfunc NewRetryLockedSource() *RetryLockedSource {\n\treturn &RetryLockedSource{\n\t\tlk: sync.Mutex{},\n\t\ts:  rand.NewSource(time.Now().UnixNano()),\n\t}\n}\n","sourceCodeStart":321,"sourceCodeEnd":348,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/backoff/retrypolicy.go#L321-L348","documentation":"RetryLockedSource in common/backoff/retrypolicy.go is a math/rand.Source wrapper that is deliberately seeded once at construction (from time.Now().UnixNano()). Calling Seed on it afterwards would break retry-backoff determinism guarantees, so the method unconditionally panics with \"internal error: call to RetryLockedSource.Seed\". It marks an unsupported operation as a programmer error.","triggerScenarios":"Calling (r *RetryLockedSource).Seed(seed int64) directly, or passing a RetryLockedSource to code that calls Seed on any rand.Source (e.g. rand.New(source).Seed(...), some shuffling/seeding utilities).","commonSituations":"Reusing a backoff policy helper that reseeds its source for reproducibility in tests; generic code that takes a rand.Source interface and defensively seeds it; wiring RetryLockedSource into a rand.Rand and then calling Seed on the Rand.","solutions":["Remove the Seed call — RetryLockedSource is seeded automatically at NewRetryLockedSource()","If deterministic seeding is needed, construct your own rand.NewSource(seed) instead of RetryLockedSource","Audit code that accepts rand.Source to ensure it does not call Seed on the provided source"],"exampleFix":"// before\nsrc := backoff.NewRetryLockedSource()\nrnd := rand.New(src)\nrnd.Seed(42) // panics\n// after\nsrc := rand.NewSource(42) // deterministic test source\nrnd := rand.New(src)\n","handlingStrategy":"validation","validationCode":"// Ensure no code path calls Seed on a source you don't own:\nif s, ok := src.(*backoff.RetryLockedSource); ok {\n    _ = s // do not Seed; already seeded at construction\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never call Seed on sources created by backoff helpers","Use your own rand.NewSource(seed) when reproducibility is required","Review generic code accepting rand.Source for implicit Seed calls"],"tags":["backoff","retry","rand","panic","misuse-guard"],"backgroundTag":"seed-not-supported","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}