{"record":{"id":"d884d190c1b1944a","repo":"chenhg5/cc-connect","slug":"unknown-or-invalid-field-s","errorCode":null,"errorMessage":"unknown or invalid field: %s","messagePattern":"unknown or invalid field: (.+?)","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"core/cron.go","lineNumber":388,"sourceCode":"\t\t\tn := int(v)\n\t\t\tjob.TimeoutMins = &n\n\t\t\treturn nil\n\t\t}\n\t\tif v, ok := value.(int); ok {\n\t\t\tjob.TimeoutMins = &v\n\t\t\treturn nil\n\t\t}\n\t}\n\t// Fallback: try to set string field via reflection\n\tif v, ok := value.(string); ok {\n\t\trv := reflect.ValueOf(job).Elem()\n\t\tf := rv.FieldByName(toExportedFieldName(field))\n\t\tif f.IsValid() && f.Kind() == reflect.String && f.CanSet() {\n\t\t\tf.SetString(v)\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn fmt.Errorf(\"unknown or invalid field: %s\", field)\n}\n\n// toExportedFieldName converts snake_case to Go exported field name (e.g., \"session_key\" -> \"SessionKey\")\nfunc toExportedFieldName(s string) string {\n\tresult := make([]byte, 0, len(s))\n\tupperNext := true\n\tfor i := 0; i < len(s); i++ {\n\t\tc := s[i]\n\t\tif c == '_' {\n\t\t\tupperNext = true\n\t\t\tcontinue\n\t\t}\n\t\tif upperNext {\n\t\t\tif c >= 'a' && c <= 'z' {\n\t\t\t\tc -= 32\n\t\t\t}\n\t\t\tupperNext = false\n\t\t}","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/cron.go#L370-L406","documentation":"updateJobField resolves the requested field name by converting snake_case to a Go exported field name via reflection; if no settable string field matches (or the field is not a string kind), it returns 'unknown or invalid field'. UpdateJob funnels generic field edits through this helper.","triggerScenarios":"CronScheduler.UpdateJob(id, \"field\", value) where `field` does not map to any CronJob exported field (after snake_case→CamelCase conversion), or maps to a non-string/ non-settable field such as an int, bool, or unexported field.","commonSituations":"Typo in field name from a /cron edit command (e.g. 'cronexpr' instead of 'cron_expr', 'namee'); API clients attempting to set numeric fields like timeout_mins through the generic string-set path.","solutions":["Use one of the supported field names exactly, e.g. cron_expr, mode, session_key, session_mode, enabled, prompt.","Check the CronJob struct definition for the exact exported field spelling.","For non-string fields (timeout_mins, enabled), use the dedicated typed handling in UpdateJob rather than the generic path."],"exampleFix":"// before\nsched.UpdateJob(id, \"cronexpr\", \"0 9 * * *\")\n// after\nsched.UpdateJob(id, \"cron_expr\", \"0 9 * * *\")","handlingStrategy":"validation","validationCode":"var allowedFields = map[string]bool{\"cron_expr\":true,\"mode\":true,\"session_mode\":true,\"session_key\":true,\"prompt\":true,\"enabled\":true}\nif !allowedFields[field] { return fmt.Errorf(\"unsupported field %q\", field) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep an allowlist of editable field names in the UI/client.","Copy field names from the CronJob struct or docs verbatim.","Use snake_case exactly as the API expects."],"tags":["go","reflection","cron"],"backgroundTag":"invalid-argument-value","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}