chenhg5/cc-connect · warning
enabled must be a boolean
Error message
enabled must be a boolean
What it means
UpdateJob validates that the "enabled" field is a Go bool before applying it. This guard exists because JSON decoders may deliver the value as a string (e.g. "true"), and if the string reached store.Update, the store would reject it after the cron entry was already removed — leaving the job enabled in the store but never firing until daemon restart. The scheduler therefore fails fast before mutating any state.
Source
Thrown at core/cron.go:579
// Validate session_mode if updating session_mode field
if field == "session_mode" {
if v, ok := value.(string); ok && v != "" {
mode := NormalizeCronSessionMode(v)
if mode != "" && mode != "new_per_run" {
return fmt.Errorf("invalid session_mode %q (want reuse, new_per_run, or new-per-run)", v)
}
}
}
// Validate enabled type up-front. Without this, a non-bool value (e.g. a
// JSON string "true" from a misbehaving API client) reaches updateJobField
// only after we've already removed the cron entry below, and store.Update
// then fails on the type mismatch — leaving the job marked Enabled in the
// store but never firing again until the daemon restarts.
if field == "enabled" {
if _, ok := value.(bool); !ok {
return fmt.Errorf("enabled must be a boolean")
}
}
// Check if reschedule is needed
needsReschedule := field == "cron_expr" || field == "enabled"
if needsReschedule {
// Remove current schedule
cs.mu.Lock()
if entryID, ok := cs.entries[id]; ok {
cs.cron.Remove(entryID)
delete(cs.entries, id)
}
cs.mu.Unlock()
}
// Update the field
if !cs.store.Update(id, field, value) {View on GitHub (pinned to 4000b2338a)
Solutions
- Pass a real bool: use value == "true" style coercion at the API boundary before calling UpdateJob
- Decode the JSON field into a typed struct with a bool Enabled field instead of map[string]any
- If the error is returned, surface it to the caller and do not retry — the job schedule is untouched
Example fix
// before
err := cs.UpdateJob(id, "enabled", rawValue) // rawValue is any from JSON
// after
enabled, ok := rawValue.(bool)
if !ok {
if s, isStr := rawValue.(string); isStr {
enabled, err = strconv.ParseBool(s)
if err != nil { return err }
} else {
return fmt.Errorf("enabled must be a boolean")
}
}
err := cs.UpdateJob(id, "enabled", enabled) Defensive patterns
Strategy: validation
Validate before calling
func validEnabled(v any) bool { _, ok := v.(bool); return ok } Type guard
en, ok := value.(bool)
Prevention
- Decode edit payloads into typed structs, not map[string]any
- Coerce JSON strings to bool at the API boundary
- Add a unit test asserting UpdateJob rejects non-bool without touching the schedule
When it happens
Trigger: Calling UpdateJob(id, "enabled", value) where value is not a bool — typically a JSON-decoded string "true"/"false" from a misbehaving API client, or any other type passed via handleCronEdit or handleCronByID.
Common situations: A platform command handler unmarshals the edit payload into map[string]any, so JSON numbers/strings lose their static types; a client sends {"enabled": "true"} instead of {"enabled": true}.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- %s must be true or false
- timeout_mins must be >= 0
- invalid cron expression %q: %w
- cron_expr must be a string
- antigravity: invalid permission behavior %q
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/16800e653e8189bc.
Report an issue: GitHub.