{"record":{"id":"12ae93e1f44e396e","repo":"zeroclaw-labs/zeroclaw","slug":"declarative-cron-job-id-invalid-job-type-ot","errorCode":null,"errorMessage":"Declarative cron job '{id}': invalid job_type '{other}', expected 'shell' or 'agent'","messagePattern":"Declarative cron job '(.+?)': invalid job_type '(.+?)', expected 'shell' or 'agent'","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-runtime/src/cron/store.rs","lineNumber":1423,"sourceCode":"                    \"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 {\n        CronScheduleDecl::Cron { expr, tz } => Ok(Schedule::Cron {\n            expr: expr.clone(),\n            tz: tz.clone(),\n        }),\n        CronScheduleDecl::Every { every_ms } => Ok(Schedule::Every {\n            every_ms: *every_ms,","sourceCodeStart":1405,"sourceCodeEnd":1441,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/cron/store.rs#L1405-L1441","documentation":"validate_decl matches decl.job_type case-insensitively against exactly two accepted values: \"shell\" and \"agent\". Any other string (typo, a model name, a provider label) falls into the catch-all arm and the declarative sync aborts before any DB write.","triggerScenarios":"job_type = \"sh\", \"bash\", \"command\", \"run\", \"Agent \" with trailing garbage, or a model/provider identifier mistakenly placed in the job_type field.","commonSituations":"Assuming the scheduler accepts arbitrary runner names; pasting a model id into job_type; renaming from another tool's cron config that uses different type names.","solutions":["Set job_type to exactly \"shell\" or \"agent\" (any capitalization works because matching is lowercased)","Double-check for trailing characters or smart quotes when copy-pasting"],"exampleFix":"# before\n[cron.cleanup]\njob_type = \"bash\"\nschedule = { kind = \"cron\", expression = \"0 4 * * *\" }\ncommand = \"rm -rf /tmp/cache/*\"\n\n# after\n[cron.cleanup]\njob_type = \"shell\"\nschedule = { kind = \"cron\", expression = \"0 4 * * *\" }\ncommand = \"rm -rf /tmp/cache/*\"","handlingStrategy":"type-guard","validationCode":"for (id, decl) in &decls {\n    let jt = decl.job_type.to_lowercase();\n    if jt != \"shell\" && jt != \"agent\" {\n        anyhow::bail!(\"cron job '{id}': job_type must be 'shell' or 'agent', got '{jt}'\");\n    }\n}","typeGuard":"fn is_supported_cron_job_type(job_type: &str) -> bool {\n    matches!(job_type.to_lowercase().as_str(), \"shell\" | \"agent\")\n}","tryCatchPattern":"if let Err(err) = zeroclaw_runtime::cron::sync_declarative_jobs(&config, &decls) {\n    if err.to_string().contains(\"invalid job_type\") {\n        eprintln!(\"config error: job_type must be 'shell' or 'agent' (case-insensitive)\");\n    }\n    return Err(err);\n}","preventionTips":["Only two job types exist: shell and agent — check against that closed set before writing config","Beware trailing spaces and smart quotes when pasting job_type values from docs or chats"],"tags":["cron","config-validation","job-type"],"backgroundTag":"config-validation-failed","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}