RETENTION_SWEEP_INTERVAL is not range-checked, so a non-positive value panics two goroutines after startup reports success #140
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found by the integration review of #111. Blocks the 1.0.0 tag: it is a crash-on-misconfiguration of exactly the kind #80 was meant to eliminate.
envDuration(internal/config/config.go:219) accepts0sand-1h. That value feedstime.NewTickerin two places:internal/database/retention.go:122internal/delivery/archive_sweeper.go:130— this second consumer is new in this milestonetime.NewTickerpanics on a non-positive duration, and both calls run in goroutines with no recover. So the process logs "Configuration loaded", reports a successful startup, and then aborts.PORTandRECEIVER_RATE_LIMITboth got lower bounds under #80. This variable was missed, and the milestone then added a second consumer of it.Definition of done
RETENTION_SWEEP_INTERVALis rejected inloadFromEnvand aborts startup with an error naming the variable, consistent with howPORTandRECEIVER_RATE_LIMITfail.0sand a negative value, asserting the failure names the variable and wraps the same sentinel error the sibling variables use.envDurationcall site for the same gap and state the result. If another duration reaches aNewTicker,NewTimeror similar without a bound, fix it here.Implementation requirements
next, PR based onnext, single commit, title ending(closes #N).TODO.md.make checkplus the Docker lint path with the cache defeated (#119).clawbot referenced this issue2026-08-12 12:38:21 +02:00
Fixed in #142.
RETENTION_SWEEP_INTERVALnow goes through a newenvPositiveDuration, which wrapsenvDurationthe wayenvPortwrapsenvPositiveIntand rejects<= 0with an error wrappingErrNonPositiveValuethat names the variable — the same failure shape asPORTandRECEIVER_RATE_LIMIT.Audit: there are exactly two
envDurationcall sites.RETENTION_SWEEP_INTERVAL(ticker in bothinternal/database/retention.go:122andinternal/delivery/archive_sweeper.go:130) is fixed.SESSION_IDLE_TIMEOUTreaches no ticker or timer — it becomessession.idleTimeout, guarded byif s.idleTimeout <= 0at both use sites, where non-positive is the documented "disabled" state — so it stays onenvDuration. The otherNewTicker/AfterFunc/WithTimeoutsites use constants or a computed backoff, none environment-configurable.Verified:
make checkexit 0 with the new subtests observed running, anddocker build --no-cache-filter=lint,builderexit 0 with thelintandbuilderstages confirmed executed rather thanCACHED(0 issues., and the new subtests passing inside the container).