{"record":{"id":"5fcd9687845b50fc","repo":"chenhg5/cc-connect","slug":"invalid-session-mode-q-want-reuse-new-per-run","errorCode":null,"errorMessage":"invalid session_mode %q (want reuse, new_per_run, or new-per-run)","messagePattern":"invalid session_mode %q \\(want reuse, new_per_run, or new-per-run\\)","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"core/cron.go","lineNumber":101,"sourceCode":"\t\treturn \"new_per_run\"\n\tdefault:\n\t\treturn s\n\t}\n}\n\nfunc validateCronJob(j *CronJob) error {\n\t// SessionKey anchors the cron execution to a platform (ExecuteCronJob\n\t// derives platformName from the prefix before \":\"). Without it the job\n\t// is persisted but fails at fire-time with the unhelpful\n\t// `platform \"\" not found for session \"\"`. Reject it up front so the\n\t// caller (management API, /cron/add, /cron edit) sees an immediate\n\t// 400 instead of a job that silently never runs.\n\tif strings.TrimSpace(j.SessionKey) == \"\" {\n\t\treturn fmt.Errorf(\"session_key is required\")\n\t}\n\tmode := NormalizeCronSessionMode(j.SessionMode)\n\tif mode != \"\" && mode != \"new_per_run\" {\n\t\treturn fmt.Errorf(\"invalid session_mode %q (want reuse, new_per_run, or new-per-run)\", j.SessionMode)\n\t}\n\tif j.Mode != \"\" {\n\t\tswitch j.Mode {\n\t\tcase \"default\", \"bypassPermissions\", \"acceptEdits\", \"plan\", \"auto\", \"dontAsk\":\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"invalid mode %q (want default, bypassPermissions, acceptEdits, plan, auto, or dontAsk)\", j.Mode)\n\t\t}\n\t}\n\tif j.TimeoutMins != nil && *j.TimeoutMins < 0 {\n\t\treturn fmt.Errorf(\"timeout_mins must be >= 0\")\n\t}\n\treturn nil\n}\n\n// CronStore persists cron jobs to a JSON file.\ntype CronStore struct {\n\tpath string\n\tmu   sync.Mutex","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/cron.go#L83-L119","documentation":"validateCronJob normalizes SessionMode and rejects any value that isn't empty, \"reuse\", or a form of \"new_per_run\" (accepting reuse/new_per_run/new-per-run after normalization). This keeps the persisted session semantics limited to known modes so the fire-time scheduler never encounters an unrecognized mode.","triggerScenarios":"Calling AddJob (or /cron add / edit) with SessionMode set to any string other than the accepted set — e.g. \"new\", \"fresh\", \"New\", \"new-per-run \" with stray characters, or a locale variant like \"always_new\".","commonSituations":"A UI dropdown sending free-text mode values; a typo like \"reuse_session\" or \"newPerRun\" (camelCase) that normalization doesn't recognize; clients written against an older spec that used different mode names; copy-paste from docs of another product.","solutions":["Use one of: \"reuse\", \"new_per_run\", or \"new-per-run\" — or omit session_mode entirely for the default behavior.","Check for typos/whitespace and use the exact lowercase snake-case form.","Update the client/UI to a fixed enum of the three accepted values instead of free text.","If you need a new mode, add it to NormalizeCronSessionMode and validateCronJob rather than sending an ad-hoc value."],"exampleFix":"// before\njob := core.CronJob{..., SessionMode: \"newPerRun\"}\ncore.AddJob(job) // 400\n// after\njob := core.CronJob{..., SessionMode: \"new_per_run\"}\ncore.AddJob(job)","handlingStrategy":"validation","validationCode":"var validSessionModes = map[string]bool{\"\": true, \"reuse\": true, \"new_per_run\": true, \"new-per-run\": true}\nfunc validateSessionMode(m string) error {\n    if !validSessionModes[m] {\n        return fmt.Errorf(\"invalid session_mode %q\", m)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := validateSessionMode(job.SessionMode); err != nil {\n    http.Error(w, err.Error(), http.StatusBadRequest)\n    return\n}\nif err := core.AddJob(job); err != nil {\n    http.Error(w, err.Error(), http.StatusBadRequest)\n}","preventionTips":["Restrict UIs and API clients to a fixed dropdown of \"reuse\" / \"new_per_run\" — never free text","Use the lowercase snake_case literal new_per_run; avoid camelCase or stray whitespace","Omit session_mode entirely when you only need the default behavior","Share a single mode-constant definition between client and server code to prevent drift"],"tags":["cron","validation","enum","scheduler"],"backgroundTag":"invalid-enum-value","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}