The cron job ran. The status says success. But the Telegram cron message never arrived. The output looks correct when you trigger it manually. But the Telegram message never comes. This is a delivery-layer failure, and it is completely separate from whether the job ran. The two layers are fully independent , a cron telegram notification not arriving does not mean the job failed. This article covers every reason a Telegram cron job delivery failure happens after a successful cron run, and the exact fix for each one.
TL;DR
- Root cause 1: Wrong chat ID , the message delivered, just not to you.
- Root cause 2: Bot token invalid or revoked , the bot cannot send anything.
- Root cause 3: Delivery mode set to none , no message was ever intended.
- Root cause 4: Bot blocked or removed from the chat , Telegram rejected the send.
- Root cause 5: Job uses agent messaging tools instead of delivery config , different failure path.
Throughout this article you will see indented blocks like the ones below. Each one is a command you can paste directly into your OpenClaw chat. Your agent will run it and report back. You do not need to open a terminal or edit any files manually.
Start here: separate the job from the delivery
The cron system has two independent components: the job execution layer (the isolated session that runs your prompt) and the delivery layer (the mechanism that sends output to your notification channel). When a Telegram notification does not arrive, the failure is almost always in the delivery layer, not the execution layer.
The first step is to confirm which layer failed.
Show me cron job [job-id] details: last run time, last run status, last run output (if available), and the full delivery config including mode, channel, and recipient.
What to look for:
- Last run status is error: The job failed before reaching the delivery step. The Telegram notification not arriving is a symptom of the job failure, not a delivery config problem. Fix the job first.
- Last run status is success but no message arrived: The job completed. Delivery failed. Continue with the root causes below.
- Last run output shows the expected content: The isolated session produced correct output. The delivery layer dropped it. Focus on Root Causes 1 through 4.
Root cause 1: wrong chat ID
This is the most common cause. The Telegram message was sent successfully , just to the wrong chat ID. The bot did not return an error because sending to a valid but wrong chat ID is not an error from Telegram’s perspective.
How to check: compare the chat ID in the job’s delivery config against your actual Telegram chat ID.
What chat ID is configured in the delivery section of cron job [job-id]? What is my Telegram chat ID as stored in the OpenClaw config? Do they match?
If you do not know your Telegram chat ID, send a message to your bot and check who sent it:
Send a test message “chat ID test” to my configured Telegram channel. If it arrives, confirm the chat ID used. If it does not arrive, tell me what error Telegram returned.
If the IDs do not match, update the job delivery config:
Update cron job [job-id] delivery: set the recipient to [correct-chat-id]. Then trigger the job immediately to confirm the message arrives.
Group chats vs. direct messages
Your personal Telegram chat ID is a positive number (e.g., 7930272159). Group chat IDs are negative numbers (e.g., -1001234567890). If you are delivering to a group and using a positive number, the message is going to someone’s personal chat. If you are delivering to your personal chat and using a negative number, it is going to a group.
Root cause 2: bot token invalid or revoked
Telegram bot tokens can be invalidated if you regenerate the token via BotFather, if the bot is deleted, or if the token was rotated and the new token was not updated in the OpenClaw config. When the token is invalid, all send attempts fail silently at the delivery layer.
Test the Telegram bot connection by sending a simple message to [your-chat-id]. Show me the full response from Telegram including any error codes. If it fails, tell me the exact error message.
A working, valid token returns a JSON message object with your bot info. An invalid token returns a 401 Unauthorized error with the message “Unauthorized”. A revoked token returns the same 401.
If the token is invalid, you need to generate a new one via BotFather and update the OpenClaw config:
My Telegram bot token has been regenerated. The new token is [new-token]. Update the Telegram channel config in OpenClaw with this token, then test by sending a message to [your-chat-id].
After updating the token
Any config change to channel credentials requires a gateway restart to take effect. After updating the bot token, restart the gateway and then trigger a test message before relying on the token for scheduled delivery.
Root cause 3: delivery mode set to none
A job with delivery mode set to none runs its isolated session, produces output, and discards that output silently. There is no Telegram message because none was configured. This is the correct behavior for jobs that deliver through other means (like the agent calling the message tool directly), but it causes confusion when you expect a Telegram notification and forgot the delivery is set to none.
Show me the delivery config for cron job [job-id]. Is delivery mode set to none? If so, what was the intended delivery mechanism for this job?
If you want the job to deliver via the announce mechanism, update it:
Update cron job [job-id] delivery: set mode to announce, channel to telegram, recipient to [your-chat-id]. Then trigger immediately to confirm delivery.
If the job was intentionally set to delivery mode none and uses the agent’s message tool for delivery, the problem is in the job prompt rather than the delivery config. See Root Cause 5.
Root cause 4: bot blocked or not started
Telegram requires that the recipient has started a conversation with the bot before the bot can send them messages. If you have never sent a message to your bot, or if you have blocked the bot, all delivery attempts fail with a 403 Forbidden error.
The same applies to groups: the bot must be a member of the group and have permission to send messages before it can deliver to that group.
Try sending a test Telegram message to [your-chat-id] and show me the full response including any error codes. If you get a 403 error, explain what that means and how to fix it.
The fix for a personal chat is to open Telegram, find the bot, and send it any message (even just “hi”). After you initiate that first message, the bot can send to you. For groups, add the bot to the group and give it posting permissions.
Root cause 5: job uses agent messaging instead of delivery config
Some cron prompts instruct the agent to send a Telegram message directly using the message tool, rather than relying on the job’s delivery config. These two delivery paths fail in different ways.
- Delivery config (announce mode): OpenClaw sends the output after the isolated session completes. Fails if the channel config is wrong.
- Agent message tool: The agent calls the message tool from inside the isolated session. Fails if the tool call fails, the channel is misconfigured, or the agent reached the message step but the tool returned an error.
Show me the full prompt for cron job [job-id]. Does the prompt instruct the agent to send a Telegram message directly using a tool call? Or does it rely on the job’s delivery config to send output after the session completes?
If the prompt uses an agent tool call for delivery, the problem is in the tool call. Trigger the job manually and watch whether the tool call appears in the output and whether it returns an error:
Trigger cron job [job-id] immediately and show me the complete output including all tool calls made during the run. Did the agent attempt to send a Telegram message? If so, what was the result of that tool call?
If the tool call failed, the error message will tell you why. Common causes: wrong chat ID in the prompt, wrong channel name, or the message tool returned a rate limit error.
How the delivery config works
Understanding the delivery config structure prevents most misconfiguration errors. The delivery object in a cron job has four fields that matter:
- mode:
none(silent),announce(send to channel), orwebhook(POST to URL). - channel: The channel plugin to use. For Telegram this is
telegram. For Discord it isdiscord. - to: The recipient identifier. For Telegram this is the chat ID as a string. For Discord it is the channel ID or user ID.
- bestEffort: If true, delivery failures are silent. If false (default), delivery failures may affect job status reporting.
Show me the raw delivery config for cron job [job-id] with all fields. Confirm the mode is announce, the channel is telegram, and the to field contains my correct chat ID.
Testing delivery independently of the job
You do not need to run the full cron job to test whether Telegram delivery is working. Send a direct test message first, confirm it arrives, then re-test the cron job with confidence that delivery is functional.
Send a Telegram message to [your-chat-id] with the text “delivery test from Gambit at [current time]”. Confirm it arrived and show me the message ID returned by Telegram.
If this fails, Telegram delivery is broken at the channel level, not the cron job level. Fix the channel config before debugging any individual cron job.
If this succeeds but cron delivery still fails, the problem is in the job’s delivery config specifically. Compare the working channel config to the job delivery config field by field.
Compare the Telegram channel configuration in openclaw.json against the delivery config for cron job [job-id]. Are the chat IDs the same? Are both using the same channel plugin? List any differences.
Timing issues and rate limits
Telegram has rate limits on how many messages a bot can send per second. If you have multiple cron jobs set to deliver at exactly the same time, the burst of simultaneous deliveries can trigger rate limiting. Some messages deliver, some are silently dropped, and the pattern looks random.
Telegram’s bot API rate limit is approximately 30 messages per second globally and 1 message per second to any individual chat. For most operators running a handful of cron jobs, this is not a practical concern. But if you have many jobs set to the same time (like all at midnight), staggering them by a few minutes eliminates any rate limit risk.
List all my cron jobs that are scheduled to deliver to Telegram within the same 5-minute window. Are any of them scheduled at exactly the same time? If so, suggest staggered times that spread the deliveries out.
Messages that are too long
Telegram has a maximum message length of 4096 characters. If the cron job output exceeds this limit, the delivery fails silently. The job ran, the output was generated, but Telegram rejected the message and returned an error that the delivery layer discarded.
Trigger cron job [job-id] manually and show me the character count of the output it would deliver to Telegram. Is it under 4096 characters?
If the output is over 4096 characters, update the prompt to summarize more aggressively. Most cron job outputs can be reduced to under 1000 characters without losing the essential information. A daily health check does not need to include the full output of every command , just the metrics that matter and any warnings.
Update the prompt for cron job [job-id]: the output delivered to Telegram must be under 1000 characters. Summarize metrics as key:value pairs on single lines. Include only values outside normal ranges and a one-line status summary. Do not include raw command output.
Verifying the full bot configuration
A working Telegram delivery requires three things to be correct simultaneously: the bot token must be valid, the recipient chat ID must be correct, and the recipient must have started a conversation with the bot. If any one of these is wrong, delivery fails. Here is how to verify all three in a single pass.
Check the full Telegram channel configuration in my OpenClaw config. Tell me: (1) the bot token (last 6 chars only for security), (2) the configured recipient chat IDs or allowFrom list, (3) whether the channel is enabled. Then send a test message to [your-chat-id] and report success or the exact error returned.
This one prompt surfaces all three conditions at once. If the test send succeeds, delivery is functional and the problem is in the cron job’s delivery config specifically. If it fails, the error message will tell you which of the three conditions is broken.
OpenClaw channel config vs. job delivery config
There are two separate places that affect Telegram delivery from a cron job, and it is easy to confuse them.
OpenClaw channel config (in openclaw.json) is the global Telegram setup: the bot token, the allowed senders, whether the channel is enabled. This config applies to all Telegram activity from OpenClaw, including cron job delivery.
Job delivery config is the per-job setting: which channel to use, which chat ID to deliver to, and what mode (announce, none, webhook). This overrides or extends the channel config for that specific job.
Show me both the global Telegram channel config in openclaw.json and the specific delivery config for cron job [job-id]. Are they consistent? Does the job delivery config reference a chat ID that is in the global allowed list?
In most setups, the job delivery config only needs to specify the mode and the recipient. The channel and bot token come from the global config. If the job delivery config is trying to override the bot token or channel settings, that is likely the source of the mismatch.
Debugging announce mode step by step
When announce mode delivery fails, the failure happens after the isolated session closes. The session completes, OpenClaw takes the session output and attempts to deliver it via the configured channel. Here is how to trace that path.
- Trigger the job manually and note the exact output text the session produces.
- Manually send that same text to your Telegram chat ID using the message tool.
- If the manual send works, the text itself is fine and delivery config is the issue.
- If the manual send fails, the problem is in the text (too long, illegal characters) or the channel config.
Trigger cron job [job-id] and capture the output text. Then immediately send that exact text to my Telegram chat ID [your-chat-id] using the message tool. Did both steps succeed? If the trigger worked but the manual send failed, what error did Telegram return?
When nothing fixes it: the nuclear option
If you have ruled out all five root causes, tested delivery independently, confirmed the bot token is valid, confirmed the chat ID is correct, and the job still does not deliver on schedule, the fastest path forward is to recreate the job from scratch with a fresh delivery config.
Delete the broken job, create a new job with identical settings, and verify delivery with a manual trigger before waiting for the first scheduled run. In practice, recreating the job clears any state that accumulated in the delivery config through edits and fixes the issue in most cases where nothing else worked.
Show me the full config for cron job [job-id] including the schedule, prompt, model, and delivery settings. I want to recreate this job from scratch. Give me the exact prompt I would use to create an identical job with a clean delivery config.
Delete cron job [job-id], then immediately create a new cron job with these settings: [settings from previous prompt]. After creating it, trigger it immediately and confirm the Telegram delivery arrives.
Monitoring delivery health on an ongoing basis
The best way to catch delivery failures before they matter is to include a delivery confirmation step in jobs you depend on. Instead of relying on the absence of a message as your signal that something broke, build a simple heartbeat that confirms delivery is working every day.
Create a cron job that runs every day at 7am America/New_York. Prompt: “Send a Telegram message to [your-chat-id]: ‘Morning check-in: [current date], all systems running.’ Nothing else.” Model: ollama/phi4:latest. Delivery: none (the agent sends the message directly).
This job is trivially simple and costs almost nothing to run (local model, no API calls). If it stops arriving, you know Telegram delivery is broken and can diagnose before any of your more important jobs fail silently. If it arrives, you have daily confirmation that the channel is healthy.
The key difference from a standard cron job: delivery mode is set to none, and the agent sends the message directly using the message tool. This tests the message tool path, not the delivery config path. To also test the delivery config path, create a second companion job with announce mode set and see that both arrive. If only the tool-based one arrives but the announce-mode one does not, your delivery config has a problem.
Telegram error codes and what they mean
When a Telegram delivery fails, the API returns an error code and a description. These are the codes you are most likely to see and what each one means for your setup.
- 400 Bad Request: chat not found , The chat ID does not exist or the bot has never been started by that user. The recipient needs to start a conversation with the bot.
- 400 Bad Request: message is too long , Output exceeds 4096 characters. Shorten the output in the job prompt.
- 401 Unauthorized , The bot token is invalid or revoked. Regenerate via BotFather and update the OpenClaw config.
- 403 Forbidden: bot was blocked by the user , The recipient has blocked the bot. They need to unblock it in Telegram before delivery can resume.
- 429 Too Many Requests , Rate limit hit. Stagger jobs that deliver at the same time, or reduce delivery frequency.
Attempt to send a test Telegram message to [your-chat-id] and show me the raw response including the HTTP status code and the full response body, whether success or error.
The raw error code eliminates guessing. If you know you have a 401, you know it is the token. If you have a 400 with “chat not found”, you know it is the chat ID or the bot not being started. The diagnostic path is direct from there.
Choosing between delivery config and agent tool calls
Every cron job has to choose how it delivers output: through the job’s delivery config (announce mode), or through explicit agent tool calls inside the prompt. Each approach has different failure characteristics, and knowing the difference helps you debug faster.
Delivery config (announce mode)
The isolated session runs, produces output, and exits. OpenClaw takes that output and delivers it through the configured channel after the session closes. The agent never calls a messaging tool inside the session.
Advantages: simple, consistent, the prompt stays focused on the task. Disadvantages: the delivery happens after the session, so the agent cannot react to a delivery failure. If delivery fails, the output is gone.
Use announce mode for: simple reports, health checks, daily summaries where the content is the output of the session and no additional formatting is needed.
Agent tool calls
The prompt instructs the agent to explicitly call the message tool with a specific text and recipient. The delivery happens inside the session, before it exits.
Advantages: the agent can format the message, conditionally send or skip based on output, send to multiple recipients, and handle tool errors. Disadvantages: more complex prompt, tool call failures surface differently.
Use agent tool calls for: conditional notifications (send only if threshold crossed), multi-recipient delivery, formatted messages that require assembly from multiple data sources.
I have a cron job that should send a Telegram notification only if disk usage is above 80%. Should I use delivery config (announce mode) or agent tool calls for this? Show me the relevant part of the prompt for each approach.
For conditional delivery, agent tool calls are the right choice. Announce mode delivers the full session output regardless of what the session found. If you want the agent to decide whether to send a message at all, that logic belongs inside the prompt.
After fixing delivery: prevent recurrence
Once you have resolved the Telegram delivery failure, take three minutes to protect against it recurring:
- Store your chat ID in memory so every job can look it up rather than hardcoding it in each job’s delivery config. A hardcoded ID gets stale; a memory entry gets updated once.
- Add a daily heartbeat job that sends a trivial Telegram message. Absence of the heartbeat is your early warning that delivery is broken.
- Audit all cron job delivery configs at once so you find any other jobs with wrong chat IDs before they fail at a bad moment.
Store my Telegram chat ID [your-chat-id] in memory with category fact and label “telegram chat ID”. I want to be able to recall it in any session without looking it up again.
List all my cron jobs that deliver to Telegram. For each one, show the chat ID in the delivery config and flag any that do not match [your-chat-id].
Running that second prompt now will surface any other jobs with the same wrong chat ID before they fail. Ten minutes of audit work prevents the same debugging session from repeating across multiple jobs. It also gives you a clean reference list of every job that is supposed to deliver to you , which is useful the next time you add a job and need to confirm the chat ID is set correctly.
Full diagnostic sequence
When a cron job Telegram notification does not arrive, run this sequence in order. Each step narrows the problem to one layer and each fix is confirmed before moving to the next.
Step 1: Show me cron job [job-id] last run status and last run result.
Step 2: Send a direct test message “test” to Telegram chat ID [your-chat-id]. Show me the result.
Step 3: Show me the full delivery config for cron job [job-id] including mode, channel, and recipient.
Step 4: Trigger cron job [job-id] immediately. After it runs, confirm whether the Telegram delivery arrived.
Step 2 isolates the channel. Step 3 isolates the job config. If Step 2 passes and Step 4 fails, the delivery config has an error. If Step 2 fails, fix the channel first. In practice this four-step sequence resolves the openclaw cron telegram notification not arriving issue in under 10 minutes for every root cause covered in this article.
Network and firewall considerations
OpenClaw sends Telegram messages by calling the Telegram Bot API over HTTPS. If your server has outbound firewall rules that block HTTPS traffic to Telegram’s IP ranges, all delivery attempts fail silently. This is uncommon on standard VPS setups but happens on hardened corporate servers or servers behind aggressive egress filters.
Test whether my server can reach the Telegram API. Run: curl -s https://api.telegram.org/bot[your-token]/getMe and show me the response. If the curl command hangs or returns a connection error, my server cannot reach Telegram.
If the curl test succeeds (returns a JSON response with your bot info), the network is not the issue. If it hangs or returns a connection refused error, your server’s outbound HTTPS to Telegram is being blocked. Check your firewall rules for any rules that restrict outbound traffic to specific IP ranges or domains, and add an outbound allow exception for api.telegram.org on port 443.
Testing without exposing your token
The curl test above uses your real bot token. Run it only in your own terminal session, not in a chat message that might be logged or shared. Ask the agent to run the test on your behalf if you prefer not to paste the token manually.
Why manual triggers deliver but scheduled runs do not
This specific pattern , works manually, fails on schedule , points to one of three conditions: a transient error at the scheduled time, a model cold-start timeout that prevents the session from reaching the delivery step, or a race condition where the scheduled job fires while the gateway is in a partially-restarted state.
The quickest way to confirm which one applies is to look at the last scheduled run’s status and output:
Show me the run history for cron job [job-id] for the last 7 days. For each run, show the trigger type (manual or scheduled), the run status, and whether delivery succeeded. Are there any runs that were scheduled but show a different status than manual triggers?
If scheduled runs consistently show errors while manual triggers succeed, the problem is timing-related. Stagger the job by 5 to 10 minutes past the typical gateway restart window, add OLLAMA_KEEP_ALIVE=-1 to prevent cold-start timeouts, and increase the job’s timeout setting to give the model more time to load.
Frequently asked questions
These questions cover the edge cases that come up most often once the five root causes above have been ruled out.
How do I find my Telegram chat ID if I do not know it?
The simplest method: open Telegram, search for your bot username, and send it any message. Then ask the agent to check the latest updates from the Telegram Bot API and return the chat ID from that message. Alternatively, forward a message from your personal Telegram account to the @userinfobot bot , it will reply with your user ID, which is your personal chat ID. For OpenClaw specifically, your chat ID is the number in the allowFrom list in the Telegram channel config.
The message arrived once but has not arrived since. What changed?
Three common causes: the bot token was regenerated after the first successful send, the chat ID in the delivery config was corrected once then reverted, or the job was edited and the delivery section was accidentally cleared. Check the current delivery config against what you remember setting, and test delivery with a direct message before triggering the cron job again.
I get the message from manual triggers but not scheduled runs. Is that possible?
Yes. Manual triggers and scheduled runs use the same delivery config, so the difference is almost always timing-related. The most common cause is that the job fires during a brief Telegram API outage or a moment when your bot token has a transient error. Check the last run status for the scheduled run and look for any error in the last run result field.
Can I deliver to both Telegram and Discord from the same cron job?
The built-in delivery config supports one destination. To deliver to multiple channels, use the agent message tool inside the prompt to send to additional destinations. Set delivery mode to announce for the primary channel, and add a step in the prompt to call the message tool for any secondary channels.
The job delivers fine to Discord but not Telegram. Is there a config difference?
Yes. Telegram delivery requires a bot token and a chat ID. Discord delivery requires a bot token and a channel ID or user ID. The config structure is similar but the field values are different. Check that the Telegram channel plugin is enabled in your OpenClaw config and that the bot token in the plugin config matches the token for your active bot.
My Telegram bot was working and then I switched servers. Now delivery fails.
The bot token itself is server-independent, so switching servers should not break the token. What breaks is the openclaw.json config that did not transfer to the new server, or transferred with the wrong values. Check the Telegram channel config on the new server and confirm the bot token and the allowed sender IDs are correctly set.
Can I test the delivery without triggering the full cron job?
Yes. Ask the agent to send a direct Telegram message to your chat ID using the message tool. This tests the channel config independently of the cron job. If the direct send works and cron delivery does not, the problem is in the job delivery config, not the channel.
Is there a way to get notified when delivery fails instead of having it fail silently?
Not automatically. The workaround is to build failure reporting into the job prompt: instruct the agent to attempt a secondary notification method (like writing to a log file or sending via a different channel) if the primary delivery fails. This requires the job to use the agent message tool for at least one delivery step rather than relying entirely on the delivery config.
