zeroclaw-labs/zeroclaw · error · anyhow::Error
Declarative cron job '{id}': shell job requires a non-empty
Error message
Declarative cron job '{id}': shell job requires a non-empty 'command' What it means
validate_decl enforces that declarative cron jobs with job_type = "shell" (the default when job_type is omitted) carry a non-empty command. The command is the entire payload a shell job executes, so a missing or blank value would dispatch a job that does nothing; validation fails during sync_declarative_jobs before any DB write.
Source
Thrown at crates/zeroclaw-runtime/src/cron/store.rs:1404
"Inserted declarative cron job from config"
);
}
}
Ok(())
})
}
/// Validate a declarative cron job definition.
fn validate_decl(id: &str, decl: &zeroclaw_config::schema::CronJobDecl) -> Result<()> {
if id.trim().is_empty() {
anyhow::bail!("Declarative cron job has empty id");
}
match decl.job_type.to_lowercase().as_str() {
"shell" => {
if decl.command.as_deref().is_none_or(|c| c.trim().is_empty()) {
anyhow::bail!(
"Declarative cron job '{id}': shell job requires a non-empty 'command'"
);
}
}
"agent" => {
if decl.prompt.as_deref().is_none_or(|p| p.trim().is_empty()) {
anyhow::bail!(
"Declarative cron job '{id}': agent job requires a non-empty 'prompt'"
);
}
if decl.shell_output_format != zeroclaw_config::schema::CronShellOutputFormat::default()
{
anyhow::bail!(
"Declarative cron job '{id}': shell_output_format is shell-only and cannot be set on an agent job"
);
}
}
other => {View on GitHub (pinned to 88bb9c8533)
Solutions
- Add command = "<your shell command>" to the [cron.<id>] table
- If the job should prompt the agent instead, set job_type = "agent" and provide a non-empty prompt
- Make sure command is not only whitespace
Example fix
# before
[cron.digest]
schedule = { kind = "cron", expression = "0 8 * * *" }
# job_type defaults to "shell" but command is missing
# after
[cron.digest]
job_type = "shell"
schedule = { kind = "cron", expression = "0 8 * * *" }
command = "./scripts/digest.sh --daily" Defensive patterns
Strategy: validation
Validate before calling
for (id, decl) in &decls {
if decl.job_type.eq_ignore_ascii_case("shell")
&& decl.command.as_deref().is_none_or(|c| c.trim().is_empty())
{
anyhow::bail!("cron job '{id}': shell job needs a non-empty 'command'");
}
} Type guard
fn shell_decl_is_runnable(decl: &zeroclaw_config::schema::CronJobDecl) -> bool {
!decl.job_type.eq_ignore_ascii_case("shell")
|| decl.command.as_deref().is_some_and(|c| !c.trim().is_empty())
} Try / catch
if let Err(err) = zeroclaw_runtime::cron::sync_declarative_jobs(&config, &decls) {
if err.to_string().contains("shell job requires") {
eprintln!("config error: a shell [cron.<id>] table is missing 'command'");
}
return Err(err);
} Prevention
- Decide the job type first, then fill exactly its required field: shell needs command, agent needs prompt
- When converting a job between types, delete the other type's fields in the same edit
- Keep one example of each job type in config comments as a template
When it happens
Trigger: A [cron.<id>] table with job_type = "shell" (explicit or by default) and no command key, command = "", or command = " " (whitespace only, trimmed to empty).
Common situations: Writing an agent-style job but forgetting to flip job_type to "agent"; creating a schedule-only stub job to test the scheduler; a YAML/TOML anchor or merge overriding command to empty.
Understand the failure class
Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.
Related errors
- Declarative cron job has empty id
- Declarative cron job '{id}': agent job requires a non-empty
- Declarative cron job '{id}': shell_output_format is shell-on
- Declarative cron job '{id}': invalid job_type '{other}', exp
- ACP request_permission failed: {} ({})
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/d48221a3189f2986.
Report an issue: GitHub.