How It Works Features Pricing Blog Error Guides
Log In Start Free Trial
Celery · Python

Fix DatabaseError: django_celery_beat.models.PeriodicTask.DoesNotExist / celery.beat.SchedulingError: schedule not found in Celery

This error occurs when Celery Beat cannot load or parse the periodic task schedule. It often happens when the schedule configuration references a task that does not exist, the schedule dict has invalid crontab syntax, or the Beat database is corrupted. Fix it by verifying task names match registered tasks, checking crontab syntax, and resetting the Beat schedule file if needed.

Reading the Stack Trace

Traceback (most recent call last): File "/app/venv/lib/python3.12/site-packages/celery/beat.py", line 345, in apply_async entry = self.schedule[name] File "/app/venv/lib/python3.12/site-packages/celery/beat.py", line 612, in setup_schedule self._when = self._calculate_next(entry) File "/app/venv/lib/python3.12/site-packages/celery/schedules.py", line 482, in remaining_estimate raise SchedulingError( File "/app/venv/lib/python3.12/site-packages/celery/beat.py", line 290, in update self._store.sync() celery.beat.SchedulingError: Received invalid schedule entry: crontab(minute='*/5', hour='25') [2026-04-10 14:32:01,234: ERROR/MainProcess] beat: Unrecoverable error in scheduler, exiting: SchedulingError('schedule not found')

Here's what each line means:

Common Causes

1. Invalid crontab syntax

The schedule uses an out-of-range value or invalid crontab expression.

app.conf.beat_schedule = {
    'cleanup-every-night': {
        'task': 'app.tasks.cleanup',
        'schedule': crontab(minute='*/5', hour='25'),  # hour 25 invalid
    }
}

2. Task name does not match registered task

The schedule references a task path that does not match any task registered with Celery.

app.conf.beat_schedule = {
    'send-digest': {
        'task': 'app.tasks.send_digest',  # actual task is 'app.tasks.email.send_digest'
        'schedule': crontab(hour=8, minute=0),
    }
}

3. Corrupted Beat schedule database

The celerybeat-schedule.db file is corrupted, causing Beat to fail on startup.

# celerybeat-schedule.db file is corrupted
# celery -A app beat --loglevel=info
# ERROR: Unrecoverable error in scheduler

The Fix

Fix the invalid crontab value (hour must be 0-23) and ensure task names exactly match the dotted path of registered Celery tasks. If the Beat schedule database is corrupted, delete celerybeat-schedule.db and restart Beat to regenerate it.

Before (broken)
from celery.schedules import crontab

app.conf.beat_schedule = {
    'cleanup-every-night': {
        'task': 'app.tasks.cleanup',
        'schedule': crontab(minute='*/5', hour='25'),
    }
}
After (fixed)
from celery.schedules import crontab

app.conf.beat_schedule = {
    'cleanup-every-night': {
        'task': 'app.tasks.cleanup',
        'schedule': crontab(minute=0, hour=2),  # 2:00 AM daily
    },
    'send-digest': {
        'task': 'app.tasks.email.send_digest',  # matches registered task path
        'schedule': crontab(hour=8, minute=0),
    }
}

Testing the Fix

import pytest
from celery.schedules import crontab
from app import create_app, celery

@pytest.fixture
def app():
    app = create_app()
    app.config['TESTING'] = True
    return app

def test_beat_schedule_has_valid_entries(app):
    schedule = celery.conf.beat_schedule
    assert len(schedule) > 0
    for name, entry in schedule.items():
        assert 'task' in entry
        assert 'schedule' in entry

def test_crontab_values_are_valid():
    # Should not raise
    crontab(minute=0, hour=2)
    crontab(hour=8, minute=0)
    crontab(minute='*/15')

def test_invalid_crontab_raises():
    with pytest.raises(Exception):
        # hour=25 should be rejected
        c = crontab(minute='*/5', hour='25')
        c.remaining_estimate(c.now())

def test_all_scheduled_tasks_are_registered(app):
    with app.app_context():
        registered = celery.tasks.keys()
        for name, entry in celery.conf.beat_schedule.items():
            assert entry['task'] in registered, f"Task {entry['task']} not registered"

Run your tests:

pytest tests/ -v

Pushing Through CI/CD

git checkout -b fix/celery-beat-schedule,git add celeryconfig.py app/tasks.py,git commit -m "fix: correct invalid crontab syntax and task names in beat schedule",git push origin fix/celery-beat-schedule

Your CI config should look something like this:

name: CI
on:
  pull_request:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    services:
      redis:
        image: redis:7-alpine
        ports:
          - 6379:6379
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
          cache: 'pip'
      - run: pip install -r requirements.txt
      - run: pytest tests/ -v --tb=short
        env:
          CELERY_BROKER_URL: redis://localhost:6379/0

The Full Manual Process: 18 Steps

Here's every step you just went through to fix this one bug:

  1. Notice the error alert or see it in your monitoring tool
  2. Open the error dashboard and read the stack trace
  3. Identify the file and line number from the stack trace
  4. Open your IDE and navigate to the file
  5. Read the surrounding code to understand context
  6. Reproduce the error locally
  7. Identify the root cause
  8. Write the fix
  9. Run the test suite locally
  10. Fix any failing tests
  11. Write new tests covering the edge case
  12. Run the full test suite again
  13. Create a new git branch
  14. Commit and push your changes
  15. Open a pull request
  16. Wait for code review
  17. Merge and deploy to production
  18. Monitor production to confirm the error is resolved

Total time: 30-60 minutes. For one bug.

Or Let bugstack Fix It in Under 2 minutes

Every step above? bugstack does it automatically.

Step 1: Install the SDK

pip install bugstack

Step 2: Initialize

import bugstack

bugstack.init(api_key=os.environ["BUGSTACK_API_KEY"])

Step 3: There is no step 3.

bugstack handles everything from here:

  1. Captures the stack trace and request context
  2. Pulls the relevant source files from your GitHub repo
  3. Analyzes the error and understands the code context
  4. Generates a minimal, verified fix
  5. Runs your existing test suite
  6. Pushes through your CI/CD pipeline
  7. Deploys to production (or opens a PR for review)

Time from error to fix deployed: Under 2 minutes.

Human involvement: zero.

Try bugstack Free →

No credit card. 5-minute setup. Cancel anytime.

Deploying the Fix (Manual Path)

  1. Run pytest locally to confirm all schedule entries are valid.
  2. Open a pull request with the schedule fix.
  3. Wait for CI checks to pass on the PR.
  4. Have a teammate review and approve the PR.
  5. Merge to main, delete the old celerybeat-schedule.db, and restart Beat in staging.

Frequently Asked Questions

BugStack validates all crontab expressions, confirms every scheduled task name maps to a registered task, and runs your full suite before marking it safe.

BugStack never pushes directly to production. Every fix goes through a pull request with full CI checks, so your team can review it before merging.

For most apps, the config file is simpler and version-controlled. Use django-celery-beat or a database-backed scheduler if you need dynamic schedule changes at runtime.

Run celery -A app inspect registered to see all tasks known to the running workers. Compare this list against your beat_schedule entries.