chenhg5/cc-connect · error
invalid session_mode %q (want reuse, new_per_run, or new-per
Error message
invalid session_mode %q (want reuse, new_per_run, or new-per-run)
What it means
validateTimerJob normalizes SessionMode via NormalizeCronSessionMode and accepts only "", "reuse", or "new_per_run" (the latter also spelled "new-per-run"). Any other SessionMode string is rejected by AddJob with the offending value quoted.
Source
Thrown at core/timer.go:75
return NormalizeCronSessionMode(j.SessionMode) == "new_per_run"
}
func validateTimerJob(j *TimerJob) error {
if strings.TrimSpace(j.SessionKey) == "" {
return fmt.Errorf("session_key is required")
}
if j.ScheduledAt.IsZero() {
return fmt.Errorf("scheduled_at is required")
}
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.MutexView on GitHub (pinned to 4000b2338a)
Solutions
- Use SessionMode: "reuse" to keep using the same session across runs.
- Use "new_per_run" (or "new-per-run") to start a fresh session for each run.
- Leave SessionMode empty ("") to accept the default behavior.
- Call core.NormalizeCronSessionMode on the value first and inspect what it maps to before AddJob.
Example fix
// before
job := &core.TimerJob{SessionKey: k, ScheduledAt: when, Prompt: p, SessionMode: "fresh"}
sched.AddJob(job)
// after
job := &core.TimerJob{SessionKey: k, ScheduledAt: when, Prompt: p, SessionMode: "new_per_run"}
sched.AddJob(job) Defensive patterns
Strategy: validation
Validate before calling
mode := core.NormalizeCronSessionMode(job.SessionMode)
if mode != "" && mode != "new_per_run" { return fmt.Errorf("bad session_mode %q", job.SessionMode) } Prevention
- Only assign SessionMode from the known set: reuse, new_per_run, new-per-run, or empty
- Normalize user input through core.NormalizeCronSessionMode before storing
- Validate session_mode values at config-load time
When it happens
Trigger: AddJob with TimerJob.SessionMode set to an unrecognized value such as "fresh", "always_new", "NEW_PER_RUN" (if not normalized case-insensitively), or a typo like "new_epr_run".
Common situations: Users guessing mode names in config.toml; configs ported from a different scheduler with different mode vocabulary; case or hyphen/underscore variations of the valid values.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- invalid mode %q
- invalid --platform-type %q, want feishu or lark
- unsupported app_type %q (only claude and codex are supported
- invalid platform type %q (want feishu or lark)
- invalid session_mode %q (want reuse, new_per_run, or new-per
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/3834b6258f528b12.
Report an issue: GitHub.