chenhg5/cc-connect · error
timeout_mins must be >= 0
Error message
timeout_mins must be >= 0
What it means
validateTimerJob rejects a TimerJob whose optional TimeoutMins pointer is non-nil but negative. A negative timeout is nonsensical for job execution; zero (nil or 0) means no timeout, positive values cap the run.
Source
Thrown at core/timer.go:85
if j.Prompt == "" && j.Exec == "" {
return fmt.Errorf("either prompt or exec is required")
}
if j.Prompt != "" && j.Exec != "" {
return fmt.Errorf("prompt and exec are mutually exclusive")
}
mode := NormalizeCronSessionMode(j.SessionMode)
if mode != "" && mode != "new_per_run" {
return fmt.Errorf("invalid session_mode %q (want reuse, new_per_run, or new-per-run)", j.SessionMode)
}
if j.Mode != "" {
switch j.Mode {
case "default", "bypassPermissions", "acceptEdits", "plan", "auto", "dontAsk":
default:
return fmt.Errorf("invalid mode %q", j.Mode)
}
}
if j.TimeoutMins != nil && *j.TimeoutMins < 0 {
return fmt.Errorf("timeout_mins must be >= 0")
}
return nil
}
// TimerStore persists timer jobs to a JSON file.
type TimerStore struct {
path string
mu sync.Mutex
jobs []*TimerJob
}
func NewTimerStore(dataDir string) (*TimerStore, error) {
dir := filepath.Join(dataDir, "timers")
if err := os.MkdirAll(dir, 0o755); err != nil {
return nil, err
}
path := filepath.Join(dir, "jobs.json")
s := &TimerStore{path: path}View on GitHub (pinned to 4000b2338a)
Solutions
- Use 0 for 'no timeout' and nil for 'unset'; never a negative number.
- Fix the sentinel: replace *TimeoutMins = -1 with TimeoutMins = nil before AddJob.
- Clamp loaded config values: if v < 0 { v = 0 } when parsing timeout_mins.
- Check the caller-side computation that produced the negative duration.
Example fix
// before
to := -1
job := &core.TimerJob{SessionKey: k, ScheduledAt: when, Prompt: p, TimeoutMins: &to}
sched.AddJob(job)
// after
job := &core.TimerJob{SessionKey: k, ScheduledAt: when, Prompt: p, TimeoutMins: nil} // nil = unset
sched.AddJob(job) Defensive patterns
Strategy: validation
Validate before calling
if job.TimeoutMins != nil && *job.TimeoutMins < 0 { return errors.New("timeout_mins must be >= 0") } Prevention
- Use nil for unset and 0 for no-timeout; never negative sentinels like -1
- Clamp parsed config values: if v < 0 { v = 0 }
- Avoid unchecked integer arithmetic when deriving timeout budgets
When it happens
Trigger: AddJob with a TimerJob whose TimeoutMins points to a negative int (e.g. int32/int pointer to -1 used as a 'default' sentinel, or arithmetic that subtracted past zero).
Common situations: Using -1 as a sentinel for 'unset' instead of leaving the pointer nil; config values like timeout_mins = -5; computing a remaining-time budget that underflowed.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- config: %s.history_max_len must be >= 0
- invalid range %q
- invalid end line
- session_key is required
- scheduled_at is required
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/6ad6d220e136fd99.
Report an issue: GitHub.