tinyhumansai/openhuman · error
Missing schedule and legacy expression for cron job
Error message
Missing schedule and legacy expression for cron job
What it means
decode_schedule reconstructs a job's Schedule from the DB row: the structured schedule JSON column when present and non-empty, otherwise the legacy expression column. When both are empty the row cannot yield any schedule and decoding bails — this is a corrupted or partially-written cron_jobs row, not a user input error.
Source
Thrown at src/openhuman/cron/store.rs:718
Some(raw) => Some(parse_rfc3339(&raw).map_err(sql_conversion_error)?),
None => None,
},
last_status: row.get(15)?,
last_output: row.get(16)?,
})
}
fn decode_schedule(schedule_raw: Option<&str>, expression: &str) -> Result<Schedule> {
if let Some(raw) = schedule_raw {
let trimmed = raw.trim();
if !trimmed.is_empty() {
return serde_json::from_str(trimmed)
.with_context(|| format!("Failed to parse cron schedule JSON: {trimmed}"));
}
}
if expression.trim().is_empty() {
anyhow::bail!("Missing schedule and legacy expression for cron job")
}
Ok(Schedule::Cron {
expr: expression.to_string(),
tz: None,
active_hours: None,
})
}
fn decode_delivery(delivery_raw: Option<&str>) -> Result<DeliveryConfig> {
if let Some(raw) = delivery_raw {
let trimmed = raw.trim();
if !trimmed.is_empty() {
return serde_json::from_str(trimmed)
.with_context(|| format!("Failed to parse cron delivery JSON: {trimmed}"));
}
}
Ok(DeliveryConfig::default())View on GitHub (pinned to 7491200858)
Solutions
- Repair the row: set a valid schedule JSON (or a legacy expression) via sqlite3 against the workspace's cron.db
- If the job is dispensable, DELETE the broken row and re-create the job through CLI/RPC
- If many rows are affected, restore the DB from backup rather than patching row by row
Example fix
-- before: row has empty schedule AND empty expression
-- after: repair with a valid schedule JSON
UPDATE cron_jobs
SET schedule = '{"type":"cron","expr":"0 9 * * *","tz":null,"active_hours":null}'
WHERE id = 'broken-job-id'; Defensive patterns
Strategy: try-catch
Validate before calling
-- integrity check runnable before operations SELECT id FROM cron_jobs WHERE COALESCE(TRIM(schedule), '') = '' AND COALESCE(TRIM(expression), '') = ''; -- any rows returned will fail decode_schedule
Try / catch
When listing jobs, wrap per-row mapping so one corrupt row degrades to a skipped entry with a warning instead of failing the entire cron list operation.
Prevention
- Never hand-edit cron.db while the core is running; use the RPC/CLI surface
- Keep workspace DB backups before migrations
- Checkpoint/stop-the-world before copying DB files for backup or sync
When it happens
Trigger: Rows touched by hand-edited cron.db (an UPDATE that cleared expression), a failed or partial migration, an interrupted restore, or a writer that inserted a job without either field. Any later cron list/get over the table hits the bail during row mapping.
Common situations: Manual sqlite3 surgery on the workspace DB; backup/sync tools copying the DB mid-write; importing jobs from an old version whose writer format changed.
Related errors
- Cron job '{job_id}' not found
- Cron job '{id}' not found
- Not running in Tauri
- OpenClaw memories table found but no content-like column was
- At least one of --expression, --tz, --command, or --name mus
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/5047c235eea9cbf1.
Report an issue: GitHub.