{"record":{"id":"bdf089662c6cda8b","repo":"zeroclaw-labs/zeroclaw","slug":"declarative-cron-job-id-shell-output-format-i","errorCode":null,"errorMessage":"Declarative cron job '{id}': shell_output_format is shell-only and cannot be set on an agent job","messagePattern":"Declarative cron job '(.+?)': shell_output_format is shell-only and cannot be set on an agent job","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-runtime/src/cron/store.rs","lineNumber":1417,"sourceCode":"    }\n\n    match decl.job_type.to_lowercase().as_str() {\n        \"shell\" => {\n            if decl.command.as_deref().is_none_or(|c| c.trim().is_empty()) {\n                anyhow::bail!(\n                    \"Declarative cron job '{id}': shell job requires a non-empty 'command'\"\n                );\n            }\n        }\n        \"agent\" => {\n            if decl.prompt.as_deref().is_none_or(|p| p.trim().is_empty()) {\n                anyhow::bail!(\n                    \"Declarative cron job '{id}': agent job requires a non-empty 'prompt'\"\n                );\n            }\n            if decl.shell_output_format != zeroclaw_config::schema::CronShellOutputFormat::default()\n            {\n                anyhow::bail!(\n                    \"Declarative cron job '{id}': shell_output_format is shell-only and cannot be set on an agent job\"\n                );\n            }\n        }\n        other => {\n            anyhow::bail!(\n                \"Declarative cron job '{id}': invalid job_type '{other}', expected 'shell' or 'agent'\"\n            );\n        }\n    }\n\n    Ok(())\n}\n\n/// Convert a `CronScheduleDecl` to the runtime `Schedule` type.\nfn convert_schedule_decl(decl: &zeroclaw_config::schema::CronScheduleDecl) -> Result<Schedule> {\n    use zeroclaw_config::schema::CronScheduleDecl;\n    match decl {","sourceCodeStart":1399,"sourceCodeEnd":1435,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/cron/store.rs#L1399-L1435","documentation":"shell_output_format (wrapped or raw) only controls how a shell job's stdout/stderr is formatted, so validate_decl rejects it on agent jobs. Setting it on job_type = \"agent\" is a config mistake that would otherwise be silently ignored; validation fails during sync_declarative_jobs before any DB write.","triggerScenarios":"A [cron.<id>] table with job_type = \"agent\" and shell_output_format = \"raw\" (any value other than the default \"wrapped\").","commonSituations":"Copying a shell job block and changing job_type to \"agent\" while leaving shell_output_format behind; experimenting with raw output on a job that was later converted to an agent job.","solutions":["Remove the shell_output_format line from the agent job","Or set job_type = \"shell\" if the raw output format was intentional"],"exampleFix":"# before\n[cron.report]\njob_type = \"agent\"\nprompt = \"Write the weekly report.\"\nshell_output_format = \"raw\"\n\n# after\n[cron.report]\njob_type = \"agent\"\nprompt = \"Write the weekly report.\"","handlingStrategy":"validation","validationCode":"use zeroclaw_config::schema::CronShellOutputFormat;\nfor (id, decl) in &decls {\n    if decl.job_type.eq_ignore_ascii_case(\"agent\")\n        && decl.shell_output_format != CronShellOutputFormat::default()\n    {\n        anyhow::bail!(\"cron job '{id}': shell_output_format is shell-only\");\n    }\n}","typeGuard":"fn agent_decl_has_no_shell_format(decl: &zeroclaw_config::schema::CronJobDecl) -> bool {\n    !decl.job_type.eq_ignore_ascii_case(\"agent\")\n        || decl.shell_output_format == zeroclaw_config::schema::CronShellOutputFormat::default()\n}","tryCatchPattern":"if let Err(err) = zeroclaw_runtime::cron::sync_declarative_jobs(&config, &decls) {\n    if err.to_string().contains(\"shell_output_format\") {\n        eprintln!(\"config error: remove shell_output_format from agent cron jobs\");\n    }\n    return Err(err);\n}","preventionTips":["Remember shell_output_format only affects shell jobs; never carry it over when switching job_type","Diff config before/after converting a job between types and remove orphaned fields"],"tags":["cron","config-validation","agent","shell-output"],"backgroundTag":"config-validation-failed","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}