{"record":{"id":"f07503000fda8139","repo":"zeroclaw-labs/zeroclaw","slug":"cli-cron-update-no-field","errorCode":"cli-cron-update-no-field","errorMessage":"At least one of --expression, --tz, --command, --name, --allowed-tool, --uses-memory, or a delivery flag (--channel, --to, --thread, --best-effort, --no-best-effort) must be provided","messagePattern":"At least one of --expression, --tz, --command, --name, --allowed-tool, --uses-memory, or a delivery flag \\(--channel, --to, --thread, --best-effort, --no-best-effort\\) must be provided","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/cron/mod.rs","lineNumber":544,"sourceCode":"            expression,\n            tz,\n            command,\n            name,\n            allowed_tools,\n            uses_memory,\n            delivery,\n        } => {\n            require_configured_agent(config, &agent_alias)?;\n            let delivery_requested = delivery.any_set();\n            if expression.is_none()\n                && tz.is_none()\n                && command.is_none()\n                && name.is_none()\n                && allowed_tools.is_empty()\n                && uses_memory.is_none()\n                && !delivery_requested\n            {\n                bail!(\"{}\", get_required_cli_string(\"cli-cron-update-no-field\"));\n            }\n\n            let existing = if expression.is_some()\n                || tz.is_some()\n                || !allowed_tools.is_empty()\n                || delivery_requested\n            {\n                Some(get_job(config, &id)?)\n            } else {\n                None\n            };\n\n            // Delivery flags are a patch over the stored config, matching this\n            // command's contract that only the fields you name change. The\n            // create paths validate inside `add_*_with_approval`; the update\n            // path does not, so validate the merged result here.\n            let delivery = if delivery_requested {\n                let existing = existing","sourceCodeStart":526,"sourceCodeEnd":562,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/src/cron/mod.rs#L526-L562","documentation":"`cron update` is a patch operation: only the fields you name change. The command therefore requires at least one of --expression, --tz, --command, --name, --allowed-tool, --uses-memory, or a delivery flag (--channel, --to, --thread, --best-effort, --no-best-effort). With none provided, it aborts immediately (i18n key 'cli-cron-update-no-field') rather than performing a silent no-op.","triggerScenarios":"`zeroclaw cron update <id>` (optionally with just the agent alias) and no mutation flags — commonly when a script conditionally builds its flag list and every condition evaluated false.","commonSituations":"Wrapper scripts passing flags only when variables are set (all empty in some runs); users expecting 'update' to refresh or re-arm a job; copy-paste commands that lost their flags.","solutions":["Add the field you want to change, e.g. `zeroclaw cron update <id> --name weekly` or `--expression '0 5 * * 1'`.","If you meant to inspect rather than change the job, use the list/show command instead.","In scripts, skip the update call entirely when the computed patch set is empty, and assert at least one flag when building the command line."],"exampleFix":"# before (script runs update with no flags)\nzeroclaw cron update abc123\n# after (guard in the caller)\nif [ -n \"$EXPR\" ] || [ -n \"$NAME\" ]; then\n  zeroclaw cron update abc123 ${EXPR:+--expression \"$EXPR\"} ${NAME:+--name \"$NAME\"}\nfi","handlingStrategy":"validation","validationCode":"struct CronPatch<'a> {\n    expression: Option<&'a str>, tz: Option<&'a str>, command: Option<&'a str>,\n    name: Option<&'a str>, allowed_tools: &'a [String], uses_memory: Option<bool>,\n    delivery_any: bool,\n}\nimpl CronPatch<'_> {\n    fn is_empty(&self) -> bool {\n        self.expression.is_none() && self.tz.is_none() && self.command.is_none()\n            && self.name.is_none() && self.allowed_tools.is_empty()\n            && self.uses_memory.is_none() && !self.delivery_any\n    }\n}\n// skip the `cron update` call when patch.is_empty()","typeGuard":null,"tryCatchPattern":"match run_cron_update(args).await {\n    Err(e) if e.to_string().contains(\"must be provided\") => {\n        // no-op patch: log and continue; nothing to fix on the CLI side\n    }\n    other => other,\n}","preventionTips":["In automation, build the patch explicitly and skip the invocation when no field is set.","Use list/show commands for inspection; reserve update for actual changes.","Unit-test flag-building code for the all-variables-empty case."],"tags":["cron","cli","argument-validation","update"],"backgroundTag":"empty-patch-rejected","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}