---
title: "Scheduled AI Job Not Running? Where to Look First"
url: https://www.insulin.dev/blog/why-a-scheduled-ai-job-did-not-run/
canonical: https://www.insulin.dev/blog/why-a-scheduled-ai-job-did-not-run/
type: Blog
description: "A scheduled AI job that didn't fire at 09:00 usually says why on its own page: the badge, the Next timestamp, a run status, or the Steps transcript."
---

# Scheduled AI Job Not Running? Where to Look First

> Canonical HTML version: https://www.insulin.dev/blog/why-a-scheduled-ai-job-did-not-run/

1.  [Home](/)
2.  /
3.  [Blog](/blog/)
4.  /
5.  Scheduled AI Job Not Running? Where to Look First

# Scheduled AI Job Not Running? Where to Look First

A scheduled AI job that didn't fire at 09:00 usually says why on its own page: the badge, the Next timestamp, a run status, or the Steps transcript.

![Shirley Guo](/authors/shirley-guo.jpg)

Shirley Guo

Sep 19, 2026

 ![Scheduled AI Job Not Running? Where to Look First](/images/blog/why-a-scheduled-ai-job-did-not-run/hero.png)

Explore AI Summary

 [![](/logos/company/openai.svg)](https://chat.openai.com/?q=Read%20and%20summarize%20https%3A%2F%2Fwww.insulin.dev%2Fblog%2Fwhy-a-scheduled-ai-job-did-not-run%2F%2C%20then%20cite%20the%20source.%20Focus%20on%20what%20it%20says%20about%20Jobs%2C%20Automation. "Summarize with ChatGPT")[![](/logos/company/anthropic.svg) ](https://claude.ai/new?q=Read%20and%20summarize%20https%3A%2F%2Fwww.insulin.dev%2Fblog%2Fwhy-a-scheduled-ai-job-did-not-run%2F%2C%20then%20cite%20the%20source.%20Focus%20on%20what%20it%20says%20about%20Jobs%2C%20Automation. "Summarize with Claude")[![](/logos/company/gemini.svg)](https://www.google.com/search?udm=50&aep=11&q=Read%20and%20summarize%20https%3A%2F%2Fwww.insulin.dev%2Fblog%2Fwhy-a-scheduled-ai-job-did-not-run%2F%2C%20then%20cite%20the%20source.%20Focus%20on%20what%20it%20says%20about%20Jobs%2C%20Automation. "Summarize with Gemini")[](https://www.perplexity.ai/search/new?q=Read%20and%20summarize%20https%3A%2F%2Fwww.insulin.dev%2Fblog%2Fwhy-a-scheduled-ai-job-did-not-run%2F%2C%20then%20cite%20the%20source.%20Focus%20on%20what%20it%20says%20about%20Jobs%2C%20Automation. "Summarize with Perplexity")

Table of Contents

-   [Where should you look first when a job didn’t run?](#where-should-you-look-first-when-a-job-didnt-run)
-   [Symptom, cause, fix: the diagnostic table](#symptom-cause-fix-the-diagnostic-table)
-   [Why did the job run at the wrong hour?](#why-did-the-job-run-at-the-wrong-hour)
-   [Why doesn’t Run now prove the schedule works?](#why-doesnt-run-now-prove-the-schedule-works)
-   [Why was a job rate limited when it barely runs?](#why-was-a-job-rate-limited-when-it-barely-runs)
-   [How do you read the Steps tab of a failed run?](#how-do-you-read-the-steps-tab-of-a-failed-run)
-   [What if the cause isn’t the job at all?](#what-if-the-cause-isnt-the-job-at-all)
-   [Frequently asked questions](#frequently-asked-questions)
-   [Takeaways](#takeaways)

_A scheduled job that didn’t run when you expected has usually left the reason on its own page. The skill is reading it in order._

* * *

The 09:00 digest did not arrive, and the instinct is to rewrite the job. Hold off: in Insulin, **nothing that fires is invisible**. Skipped and rate-limited runs still leave a row, and a failed run keeps the transcript of what it did before it failed. For setting a job up rather than debugging one, see [how to schedule a recurring AI agent job](/blog/how-to-schedule-a-recurring-ai-job/).

## Where should you look first when a job didn’t run?

**Open the job and read four things in order: the Active or Off badge, the Next timestamp, the newest row of the Runs table, and — for a failed run — its Steps tab.** An **Off** job will not fire on its own, a blank **Next** means the schedule is frozen, and _None yet._ in the Runs table means the job has never fired.

## Symptom, cause, fix: the diagnostic table

**Find what you see in the first column; the other two give the cause and the control that fixes it.**

What you see

What it means

What to do

**Off** badge, or an **off** tag in the list

Switched off; it will not fire on its own

Turn on the **Enable / Disable** switch

**Run now** works, but the schedule never fires

**Run now** bypasses the enabled check

Check the badge, then **Next**

It fired at the wrong hour

No timezone: the expression runs on the service’s clock

Compare the run’s **Started** time with the hour you meant; change the hour in the expression

**Next** is blank

Disabled or just re-enabled, so the schedule is frozen

Enable it; blank right after re-enabling is expected

The Runs table reads _None yet._

The job has never fired

Badge, then **Next**; for a push job, check that events arrive

**Filtered**

The filter returned false, so the run was skipped

Compare the filter with a payload the job received

**Rate limited**

The job hit 60 runs in an hour, or the organization hit 300

The limits are fixed: start the job less often

**Run now** came back **Filtered** or **Rate limited**

**Run now** takes the real trigger path, filter and limits included

Test the filter with a sample payload, over REST or through the assistant

**Run** rejected with _Job already has an in-flight run._

One run at a time, and one is active

Let it finish, or **Terminate** it

A REST run call answers `400`

The run endpoint accepts manual jobs only

Use the trigger endpoint the error names

**Failed**

The agent encountered an error

Select the run; it opens on **Steps**

Several jobs went quiet at once

AI is paused for a billing reason; jobs are refused before the model is called

Read the banner at the top of **Settings → Billing**

A colleague’s job is missing from your list

Jobs are private to their creator, organization admins included

Ask the owner

Filters and the full set of run statuses have posts of their own: [which events actually run a job, and which get filtered](/blog/which-events-actually-run-a-job/), and [how to see past runs of a scheduled AI job](/blog/ai-job-run-history-and-runs-table/).

## Why did the job run at the wrong hour?

**Because no timezone is attached to a cron expression.** `0 9 * * 1-5` means 09:00 on the service’s clock, not 09:00 where you are, and the expression is the whole schedule: no timezone field, no start or end date.

**The runs table shows when it actually fired.** Each run’s **Started** time is shown in your own time, so compare it with the hour you meant, while **Next** counts down to the upcoming run (for example, _in 5h_). If the hour is wrong, change it in the expression — the Jobs app has no edit form, so ask the assistant or send a `PATCH` to the REST API — and check **Next** again. Re-check it after a daylight-saving change, too: an expression on the service’s clock is not guaranteed to follow your local hour.

## Why doesn’t Run now prove the schedule works?

**Because Run now skips the one check that stops a schedule: whether the job is switched on.** **Run now is** the button on a cron or push job that fires it immediately, as if its schedule or event had arrived. Because it bypasses the enabled check, it works on a switched-off job — handy for testing a paused automation, useless as proof that the schedule will fire.

Everything else matches a real run. **Run now** takes the same path a real tick or event takes, so it is **filtered and rate limited exactly like an automatic run**. The in-app button fires with an empty payload; the REST trigger endpoint and the assistant accept a sample payload to exercise the filter.

Running a _manual_ job — with **Run**, or its REST counterpart, the run endpoint — is the one manual path that skips the rate limit. The run endpoint accepts manual jobs only: on a cron or push job it answers `400`, naming the trigger endpoint to use instead. Either way, the in-flight rule holds — one run at a time.

## Why was a job rate limited when it barely runs?

**Because two limits apply, and only one belongs to the job.** Runs that Insulin starts for you — cron ticks and arriving push events — are capped at **60 per hour per job** and **300 per hour per organization**, over a rolling one-hour window. A run past either is recorded as **Rate limited** instead of executing.

A job that fires once a morning is nowhere near its own 60, so the organization’s 300 is the likely cause — possibly used up by jobs that, being private to their owners, neither you nor an administrator can see. The limits are fixed, so the fix is fewer starts: a filter on a push job, or a less frequent expression.

## How do you read the Steps tab of a failed run?

**Select the run: a failed run opens on Steps, where the reason usually is.** **Steps is** the run’s tool-call transcript — which tools ran, in what order, each call’s **Args** and its **Result** or **Error**, and how long each took. It is persisted, not reconstructed, so a run that threw keeps everything it did before it failed. Work back from the last **Error** and the **Args** it was sent.

The two empty states differ. _This run recorded no steps._ means the run did no tool work; _No transcript recorded_ means it predates transcripts or ended before it began work. The **Input** tab holds what the run received — for a push run, the event payload.

## What if the cause isn’t the job at all?

**Two causes never show up in a job’s own settings: a billing pause, and a job that belongs to someone else.**

### AI is paused for the organization

When AI is paused for a billing reason, a request that has not started — a job’s included — is refused before the model is called. If several jobs went quiet at once, read the banner at the top of **Settings → Billing** first: it names one of four reasons, each with its own fix, and service resumes automatically once the cause is cleared. Adding credit does not clear a spending limit you set yourself; the [When AI Pauses documentation](https://doc.suger.io/insulin/billing/when-ai-pauses/) covers all four.

### The job belongs to someone else

A job is private to its creator: **only its owner** can see it, run it, edit it, or delete it, organization administrators included. A colleague’s job will not appear in your list or in a channel’s **Jobs** tab, and while its owner is away nobody else can run it.

## Frequently asked questions

### Why did my scheduled job run at the wrong time?

Because no timezone is attached to a cron expression, so it runs on the clock of the service rather than yours. Compare past runs’ Started times with the hour you meant, and use Next, which counts down to the upcoming run, to confirm a change.

### Does Run now prove a scheduled job will fire?

No. Run now bypasses the enabled check, so it works even on a job that is switched off. It does pass through the filter and the hourly rate limits, exactly like a real tick or event.

### What are the rate limits on Insulin jobs?

Runs that Insulin starts for you, from a cron tick or a push event, are capped at 60 per hour per job and 300 per hour per organization, over a rolling hour. The limits are fixed, and a run over either is recorded as Rate limited.

### Can an admin see or run a job someone else created?

No. A job is private to the person who created it. Only its owner can see it, run it, edit it, or delete it, and that includes organization administrators.

### Why does the REST run endpoint return 400?

Because it accepts manual jobs only. Called on a cron or push job, it answers 400 and names the trigger endpoint to use instead.

## Takeaways

-   Read a job in order: the badge, **Next**, the newest run, then **Steps**.
-   A cron expression carries no timezone. Check **Started** and **Next**, not the digits.
-   **Run now** skips the enabled check, but not the filter or the rate limits.
-   The limits are 60 runs per hour per job and 300 per organization, rolling and fixed.
-   Only a job’s owner can see or run it — organization administrators included.

For what [scheduled AI jobs in Insulin](/jobs/) can automate in the first place, start with the product page; the [Jobs documentation](https://doc.suger.io/insulin/jobs/) is the full reference for runs, limits and triggers.

## Sources

Primary sources for the platform rules cited above. Last verified September 19, 2026. Cloud providers change fees, eligibility, and program terms without notice — check the source before relying on a figure.

-   [Suger docs: Jobs](https://doc.suger.io/insulin/jobs/) — No timezone field and the Next timestamp, the Active and Off badges, run statuses, the per-job and per-organization hourly limits, Run versus Run now, the in-flight rule, owner-only access, the Steps transcript, and the REST run endpoint's 400 for cron and push jobs
-   [Suger docs: When AI Pauses](https://doc.suger.io/insulin/billing/when-ai-pauses/) — Requests that have not started, jobs included, are refused before the model is called; the four banner reasons and how service resumes

## Keep reading

-   [JobsHow to Build an AI Executive-Briefing AgentAug 24, 2026](/blog/ai-executive-briefing-agent/)
-   [JobsAI Agent Failure Handling: Retries to RollbacksAug 20, 2026](/blog/ai-agent-failure-handling/)
-   [AutomationAI Agent Observability: What Business and IT Teams Should MonitorAug 20, 2026](/blog/ai-agent-observability/)
-   [JobsHow to See Past Runs of a Scheduled AI JobAug 18, 2026](/blog/ai-job-run-history-and-runs-table/)

[Browse every post on the Insulin Blog](/blog/)

### Stay Updated

Get the latest Cloud GTM insights, product updates, and marketplace strategies delivered to your inbox.
