Buildmerce

Magento 2 · Troubleshooting · Field guide 02

Magento 2 cron not running?
Find the broken step before you restart.

A cron entry, a running process and a completed business task are different pieces of evidence. Trace the failure from launch to execution—and prove automatic recovery.

01 / LaunchDoes the scheduler invoke Magento?
02 / ScheduleIs the expected work created?
03 / ExecuteDoes due work finish correctly?

The short answer

When Magento 2 cron appears to stop, first identify whether the scheduler failed to launch Magento, Magento stopped creating the expected schedule, or a particular task stopped completing. Reinstalling cron cannot repair every failure in that chain.

Start with the affected outcome: delayed asynchronous order emails, stale scheduled indexes, an integration backlog or a missed custom export. Record the job code, expected frequency and first known failure. If you need the wider operational picture, use our Magento 2 health-check guide.

Choose your evidence

Which failure pattern do you have?

This local decision aid suggests the next investigation. It does not connect to your store or diagnose it automatically.

Start with the evidence window

Record the affected job and expected frequency. Use the bounded SQL queries below against the primary application database; compare two snapshots. Avoid interpreting a missing row without checking retention and the expected schedule.

Go to the relevant checks →

Scope, assumptions and command safety

This guide targets Linux-hosted Magento Open Source and Adobe Commerce 2.4.x. Commands and SQL are documentation-reviewed examples, not a test certificate for every release or hosting model.

  • Run Magento CLI commands as the filesystem owner in the active application root. Substitute the deployment’s actual PHP binary for php.
  • Shell inspections and SQL SELECTs below do not intentionally change store configuration. Application bootstrap may still write logs or generated files.
  • Run SQL through an existing authorized database client, preferably with a read-only account. Use the primary application database; replicas may lag. Replace cron_schedule with the prefixed table name where applicable.
  • Keep credentials, customer details and raw exception messages out of public reports. The bounded queries deliberately omit the messages column.

Adobe Commerce Cloud: inspect the project’s .magento.app.yaml and platform scheduling. A missing traditional user crontab is not sufficient evidence of failure there. Follow Adobe’s Cloud cron guidance rather than installing a second launcher.

Layer 1 / Launch

1. Verify what actually launches Magento

Read-only inspection
whoami
pwd
command -v php
php -v
php --ini
php bin/magento --version
crontab -l

On a conventional host, compare the cron entry with your active release directory and intended PHP binary. A correct entry under another user does not prove this deployment is covered. A command copied before a release switch may still point at old code.

Inspect the operating-system scheduler using your hosting tools. On Ubuntu/Debian with systemd and sufficient access, these are useful observations:

Read-only inspection
systemctl is-active cron
journalctl -u cron --since "30 minutes ago" --no-pager

The process-filter example later uses rg (ripgrep); use your host’s process viewer if it is unavailable. Other distributions may use crond; containers and managed hosts may use another launcher entirely. A service being active only proves the service is up. Look for attempts to execute this application’s command, then correlate those attempts with Magento evidence.

Expected: the intended scheduler repeatedly invokes the correct release, owner and PHP binary. If not: investigate a missing entry, stopped service, changed release path or incompatible CLI PHP configuration. Do not change permissions recursively to make the symptom disappear.

Layer 2 / Schedule

2. Inspect a bounded window of recent jobs

Use a time window appropriate to the task. One hour is useful for frequently scheduled work, but insufficient for a daily or weekly job. Check clock alignment before comparing application, database and host timestamps. These SQL windows assume a UTC database session; have your database operator confirm it before interpreting timestamp comparisons.

Read-only inspection
date -u
# In your database client, run the SQL below.
Read-only SQL · replace table prefix if needed
SELECT UTC_TIMESTAMP() AS observed_utc,
       @@session.time_zone AS session_time_zone;

SELECT schedule_id, job_code, status,
       created_at, scheduled_at, executed_at, finished_at
FROM cron_schedule
WHERE scheduled_at >= UTC_TIMESTAMP() - INTERVAL 1 HOUR
ORDER BY scheduled_at DESC, schedule_id DESC
LIMIT 100;

Then filter for the exact job you are investigating. The code below is an example for scheduled index updates; custom integrations have their own job codes.

Read-only SQL · one affected job
SELECT schedule_id, job_code, status,
       scheduled_at, executed_at, finished_at
FROM cron_schedule
WHERE job_code = 'indexer_update_all_views'
  AND scheduled_at >= UTC_TIMESTAMP() - INTERVAL 1 HOUR
ORDER BY scheduled_at DESC, schedule_id DESC
LIMIT 30;

Take a second snapshot after the relevant scheduling interval. Compare the same rows as well as new rows. A list of old successes can coexist with a current outage. Missing history can reflect cleanup, a wrong database, an incorrect job code or a task that is not due—not just a broken launcher.

Layer 3 / Execution

3. Interpret states in context

What to investigate next—not an automatic diagnosis
ObservationPossible interpretationNext evidence
Future pending rowsExpected scheduled workRecheck after the due time
Due rows remain pendingExecution is delayed or the group is not reachedLaunch history, group configuration, worker duration and clock
MissedThe configured start window expiredDelay and schedule_lifetime for the affected group
ErrorAn attempted task failedCorrelated exception and dependency failure
Running across repeated snapshotsLong work or an interrupted executionProcess, workload and database wait evidence
SuccessThis recorded task finished without a reported execution failureThe actual business outcome

A growing count by itself is not enough. Ask which tasks are due, how old the oldest due task is, and whether the delay exceeds the normal workload for that store. Pending work scheduled for tomorrow is not today’s backlog.

For a custom job, confirm its expected frequency and group with the module maintainer. Check effective configuration rather than assuming the XML schedule is the only source.

4. Match job timestamps to errors

Read-only inspection
tail -n 100 var/log/cron.log
tail -n 100 var/log/exception.log
tail -n 100 var/log/support_report.log

Inspect the launcher’s redirected output too; it may be a different file, such as var/log/magento.cron.log. A PHP startup failure can happen before Magento writes its own log. Missing log files can reflect rotation or logging configuration.

Correlate one job code and one execution window. Common investigation paths include an unavailable remote API, failed database access, a missing class after a deployment, or resource exhaustion. Preserve a sanitized exception signature and timestamp before applying a fix.

If unrelated jobs continue to finish while one repeatedly errors, focus on that task first. Restarting the system scheduler may not change the task’s failing dependency.

5. Check cron groups and queue consumers separately

A launcher restricted to one group cannot establish that every group is covered. Review intended group coverage and custom module definitions. The scheduling interval and allowed start window also influence whether a delayed invocation can run due work. See Adobe’s cron-group configuration reference.

Queues introduce another boundary. The cron runner may start consumers, or the host may supervise them separately. Inspect only the relevant runner configuration locally; do not paste the complete environment configuration into a support ticket.

Read-only inspection
php bin/magento queue:consumers:list
# Linux process snapshot; inspect locally for sensitive arguments.
ps -eo pid,ppid,user,etime,args | rg "[b]in/magento (cron:run|queue:consumers:start)"

The consumer list shows registrations, not throughput. An absent process can be normal for a short-lived worker, and a present process may be idle. Confirm queue age, expected messages and completed work before launching extra consumers. Refer to Adobe’s queue process-management guidance.

6. Choose the fix supported by evidence

Remediation requires deployment-specific judgment
EvidenceTargeted response
Launcher missing on a conventional hostBack up the intended owner’s crontab; install the reviewed Magento entry
Wrong PHP binary or release pathCorrect that entry and verify bootstrap with the intended runtime
One task repeatedly errorsRepair its module or dependency, then verify that task
Long tasks delay executionInvestigate workload, locks and capacity; consider smaller work units
A row appears stuck runningEstablish worker/process state before any targeted recovery

State-changing example: only after confirming the conventional-host entry is missing, back up the application owner’s crontab using the host’s normal procedure. Review and install with:

Changes scheduling · conventional host only
php bin/magento cron:install

Do not add --force casually. Preserve existing application and custom scheduling. For a controlled manual execution, first rule out conflicting workers and identify the group. This is not a read-only health check:

Executes due work · example group, not a single job
php bin/magento cron:run --group="default"

A manual invocation can create schedules before work becomes due. Observe the due time and the next appropriate execution; two immediate commands are not a substitute for checking timing. The group command does not select a single job code, and a completion message does not prove every business task succeeded.

Avoid blanket recovery commands: do not truncate cron history, mark every running row as success, kill all PHP processes or remove lock files indiscriminately. Those actions can destroy evidence or interrupt unrelated work. Recovery should match the affected task, host and release.

Illustrative timeline

Worked example: new rows, no completed work

This is a simulated example, not a customer incident. Assume vendor_inventory_sync is a custom job expected every five minutes.

Simulated evidence · timestamps normalized to UTC
10:00  scheduled_at=10:00  status=pending  executed_at=NULL
10:06  same row           status=missed   executed_at=NULL
10:06  unrelated job      status=success finished_at=10:05

What this supports: the target did not begin within its allowed window. Another job finishing makes a total application-wide stop less likely.

What it does not establish: the cause. Investigate the target’s group, effective schedule and start window, earlier long work, and launcher coverage. Do not invent a module exception when execution never started.

After correcting the confirmed cause, the evidence you want is a newly due row with a sensible execution/finish time, followed by a successful downstream inventory update. Keep watching automatic cycles after the manual test.

Prove automatic recovery

A manual success is a useful test, but it does not establish the launcher will run unattended. Record recovery evidence that someone else can review:

  1. The application owner, release and PHP binary used by the scheduler are confirmed.
  2. New due work for the affected job is created and completed over several expected automatic cycles.
  3. The oldest overdue work stops aging; errors and missed jobs do not continue accumulating unexpectedly.
  4. The downstream result is correct: the catalog update is visible, the export arrives or a controlled email reaches its destination.
  5. The alert recipient and next review are assigned.

For infrequent jobs, define an observation period that includes the next due execution. An email-sent flag does not prove inbox delivery; an indexer success does not prove cache freshness. Use the wider health-check handoff checklist to record related findings.

Prevent the next silent failure

Track the age of the last relevant successful execution, overdue work and recurring task errors against a documented expected frequency. Review these checks after release-path, PHP, scheduler and module changes.

Application monitoring also has a dependency: if its own cron stops, it may stop producing fresh results or alerts. Pair internal checks with an independent heartbeat or an external review of missing observations.

Buildmerce Health Guard includes cron status monitoring, with scheduled checks and alerts described for Pro. Confirm the current product coverage and configuration; do not assume that an internal monitor independently detects its own scheduler outage.

Common questions

Why does Magento say cron ran while emails are still delayed?

The launcher or cron command can finish without proving the relevant email task ran successfully. Inspect that task, asynchronous email configuration, provider logs and inbox delivery.

Should I delete pending or missed cron rows?

Not as a first troubleshooting step. Preserve the history, identify why work is delayed and plan task-specific recovery. Removing rows does not repair a broken dependency.

Can I use the same fix on Adobe Commerce Cloud?

Cloud uses platform-managed configuration. Review its scheduling definitions and deployment procedures rather than installing an additional traditional crontab.

Is one running job proof that cron is stuck?

No. Compare duration with expected workload, active processes and repeated observations. Investigate before interrupting a worker.

Sources & revision notes

October 27, 2026 · First edition. Documentation-reviewed commands, bounded SQL, local investigation selector and recovery criteria. Examples are illustrative; no customer logs are published.

Continue with the complete Magento 2 health check, browse all Magento guides or send a technical correction.