{"record":{"id":"c395aa42743a60b4","repo":"chenhg5/cc-connect","slug":"invalid-mode-q-want-default-bypasspermissions","errorCode":null,"errorMessage":"invalid mode %q (want default, bypassPermissions, acceptEdits, plan, auto, or dontAsk)","messagePattern":"invalid mode %q \\(want default, bypassPermissions, acceptEdits, plan, auto, or dontAsk\\)","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"core/cron.go","lineNumber":107,"sourceCode":"func 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\n\tjobs []*CronJob\n}\n\nfunc NewCronStore(dataDir string) (*CronStore, error) {\n\tdir := filepath.Join(dataDir, \"crons\")\n\tif err := os.MkdirAll(dir, 0o755); err != nil {","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/cron.go#L89-L125","documentation":"validateCronJob restricts the optional Mode (permission mode) field to a fixed allowlist: default, bypassPermissions, acceptEdits, plan, auto, or dontAsk. Any other non-empty string is rejected at job creation so the scheduler never persists a job with an unsupported permission mode.","triggerScenarios":"Calling AddJob (or the /cron add / edit endpoints) with Mode set to an unrecognized string such as \"safe\", \"yolo\", \"normal\", \"YOLO\", or an agent-specific mode not in the allowlist.","commonSituations":"Users copying mode names from another tool's CLI flags (e.g. \"dangerously-skip-permissions\"); case mismatches like \"DEFAULT\" or \"AcceptEdits\"; older config files carrying modes from previous versions that were renamed; UIs allowing free-text mode entry.","solutions":["Set Mode to one of exactly: \"default\", \"bypassPermissions\", \"acceptEdits\", \"plan\", \"auto\", or \"dontAsk\" — or omit the field for the default.","Fix casing to match the allowlist exactly (e.g. \"bypassPermissions\", not \"BypassPermissions\").","Replace legacy mode names from older configs with the current allowlist equivalents.","Constrain the management UI/API client to a fixed enum of the six accepted values."],"exampleFix":"// before\njob := core.CronJob{..., Mode: \"dangerously-skip-permissions\"}\ncore.AddJob(job) // 400\n// after\njob := core.CronJob{..., Mode: \"bypassPermissions\"}\ncore.AddJob(job)","handlingStrategy":"validation","validationCode":"var validModes = []string{\"default\", \"bypassPermissions\", \"acceptEdits\", \"plan\", \"auto\", \"dontAsk\"}\nfunc validateMode(m string) error {\n    for _, v := range validModes {\n        if m == v { return nil }\n    }\n    return fmt.Errorf(\"invalid mode %q\", m)\n}","typeGuard":null,"tryCatchPattern":"if err := validateMode(job.Mode); 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":["Copy mode strings exactly from the allowlist — casing matters (bypassPermissions, acceptEdits)","Map legacy mode names (e.g. from older configs) to current ones at load time","Expose only the six allowed modes in management UIs and API clients","Omit Mode entirely for default permission behavior instead of guessing a value"],"tags":["cron","validation","enum","permissions"],"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"}