The cron job ran. The logs show it completed. But nothing arrived in your chat. No message, no summary, no notification. The job executed perfectly and then delivered its result to nobody.
This is almost always a delivery configuration issue, not a scheduler failure. OpenClaw’s cron runs reliably; what happens to the output after the run is a separate pipeline with its own rules, and four of those rules produce exactly this silent outcome. Here is how to find which one bit you, and how to make scheduled jobs actually talk to you.
Step 1: Confirm the run and read its output
Start with run history, then look at the job’s resolved delivery route:
Split the problem in two at this point. If the run did not complete, the job itself is the problem (bad prompt, failing command, model error), not delivery. If the run completed, delivery is the problem, and the four causes below cover every way a completed run stays silent. Note that run history lives under openclaw cron runs; the tasks command family inspects durable TaskFlow state, which is a different system, so do not go looking for cron runs there.
Cause 1: The run output was only NO_REPLY
The most common cause, and the one that feels most like a bug. When an isolated cron run ends with only the silent token NO_REPLY as its output, OpenClaw treats it as intentionally non-deliverable and suppresses delivery entirely. Command jobs that print only NO_REPLY get the same treatment: nothing is posted back to chat.
This happens when your job instructions tell the agent to stay quiet unless something important happened, and the run found nothing worth reporting. It is working as designed. If you expected a confirmation message anyway, adjust the job prompt to always end with a short summary line (for example, state that the check ran and found nothing), or accept that silence means no news.
Cause 2: No announce target, or delivery mode is none
Cron jobs need a delivery instruction. Three modes exist: announce fallback-delivers the final text to a target if the agent did not already send; webhook POSTs the finished payload to a URL; none means the runner never fallback-delivers, period. A job created with --no-deliver (or delivery.mode: "none") runs and stores its result in history, then stays quiet by design.
Also worth knowing: for isolated jobs, chat delivery is shared, not exclusive. Even with --no-deliver, the agent can still use its message tool during the run when a chat route is available; announce, webhook, and none only control what the runner does with the final reply after the agent turn finishes. And DM pairing-store approvals are never fallback automation recipients: if a scheduled job should proactively message you, set delivery.to explicitly or configure the channel’s allowFrom entry.
Cause 3: The announce target is missing, wrong, or stale
When the job does announce but the target is bad, delivery fails without an obvious error. Check the resolved route, not your memory of the config:
user@host:~$ openclaw cron show <jobId> # Includes the resolved delivery route: channel, target, and mode.
Compare the resolved target against your live accounts. A channel that was renamed, an account that was re-authed to a new bot, or a chat ID from an old group all qualify as stale targets. When a channel value is explicit, the target prefix must name the same provider: channel: "whatsapp" with to: "telegram:123" is rejected on purpose rather than misdelivered. For Telegram forum topics, the target syntax is -1001234567890:topic:123.
Cause 4: The channel rejected the send
The job can complete while the delivery attempt fails at the channel. Tail the log during a manual trigger and look for unauthorized, Forbidden, or 401/403 around the send time. Then confirm the channel is healthy on its own:
If the channel probe fails or shows stale credentials, fix the channel first; a cron job cannot deliver through a channel that is not connected. If the probe is healthy but the send still 403s, the problem is target authorization (cause 3 territory), not transport.
The scheduler status capture above is from a live host: cron is enabled, and jobs and run history persist in the sqlite state store (with a JSON file path kept for compatibility). Two storage details matter for debugging. First, if openclaw cron list shows nothing while the scheduler reports jobs, your job store may be legacy; the CLI itself suggests running openclaw doctor --fix to normalize legacy cron storage. Second, run history survives gateway restarts because it lives in the state store, so a silent run from yesterday is still inspectable today.
Know your job type before debugging delivery. Agent jobs run a model turn and deliver its final text; command jobs (--command) run a deterministic script in the scheduler, capture stdout and stderr, and deliver process output (stdout wins, stderr fills in when stdout is empty, and a non-zero exit code records the run as an error and can trigger failure alerts). Isolated agent jobs start a fresh session per run, while session:<name> jobs persist context across runs. Delivery rules apply the same way to both job types, which keeps this guide valid for either.
The fastest diagnosis loop
Run the job manually while watching logs. This collapses all four causes into one observable moment:
user@host:~$ openclaw logs --follow & :~$ openclaw cron run <jobId>
The log will show one of four things: the NO_REPLY suppression, the skipped fallback for a none delivery mode, a rejected or unresolvable announce target, or the channel’s auth error. Whichever appears names the fix. The diagram stacks the causes in the order to check them:

Failure alerts, for the runs that must never be silent
For jobs where silence is unacceptable, OpenClaw can alert on failure: job.delivery.failureDestination overrides the destination for failure notifications per job, and when it is unset, a job that already delivers via announce falls back to its primary announce target. This is separate from normal-run delivery, so you can have a job that stays quiet on success but still pages you when it errors. Failure destinations are supported on isolated jobs (or webhook jobs) only.
Related fixes
Cron and heartbeat are cousins, so if your scheduled agent never fires at all, see the heartbeat troubleshooting guide. For messages that get lost after delivery starts, channel routing and the Telegram identity fix cover the rest of the chain. New to OpenClaw? Start with The Complete OpenClaw Guide.
Not Ready to Self-Host? Try ClawTrust
Building agents locally is powerful, but managing infrastructure, security, and scaling takes effort. ClawTrust provides managed OpenClaw hosting: your agents run securely in the cloud with automatic scaling, no DevOps overhead, and 24/7 monitoring.
This post contains affiliate links. If you buy through them, I may earn a small commission at no extra cost to you.

