bytedance/deer-flow · critical · SystemExit
scheduler.multi_instance=true requires database.backend='pos
Error message
scheduler.multi_instance=true requires database.backend='postgres'. database.backend is '{backend}'. Set scheduler.multi_instance=false or configure Postgres. What it means
SystemExit raised at Gateway startup (deps.py validation) when scheduler.multi_instance=true but database.backend is not 'postgres'. Multi-instance scheduling relies on Postgres-level coordination (row locks / SKIP LOCKED-style claiming) that SQLite/memory backends cannot provide, so the process refuses to boot rather than double-firing scheduled tasks.
Source
Thrown at backend/app/gateway/deps.py:96
This gate runs once at startup before any persistence engine is
initialised so the error message is clear and the process exits
immediately.
"""
try:
workers = int(os.environ.get("GATEWAY_WORKERS", "1"))
except (TypeError, ValueError):
workers = 1
scheduler = getattr(config, "scheduler", None)
multi_instance_requested = bool(getattr(scheduler, "multi_instance", False))
multi_instance_scheduler = bool(getattr(scheduler, "enabled", False) and multi_instance_requested)
backend = getattr(config.database, "backend", None)
run_events_backend = getattr(getattr(config, "run_events", None), "backend", None)
run_ownership = getattr(config, "run_ownership", None)
if multi_instance_requested and backend != "postgres":
raise SystemExit(f"scheduler.multi_instance=true requires database.backend='postgres'. database.backend is '{backend}'. Set scheduler.multi_instance=false or configure Postgres.")
if multi_instance_requested and run_events_backend != "db":
raise SystemExit(f"scheduler.multi_instance=true requires run_events.backend='db'. run_events.backend is '{run_events_backend}'. Set scheduler.multi_instance=false or configure run_events.backend: db.")
if multi_instance_requested and (run_ownership is None or not run_ownership.heartbeat_enabled):
raise SystemExit("scheduler.multi_instance=true requires run_ownership.heartbeat_enabled=true so peer runs retain a valid lease. Set scheduler.multi_instance=false or enable run ownership heartbeats.")
if workers <= 1:
return
if config.scheduler.enabled and not multi_instance_scheduler:
raise SystemExit(f"GATEWAY_WORKERS={workers} cannot run with scheduler.enabled=true because each worker starts its own scheduler. Set GATEWAY_WORKERS=1, scheduler.multi_instance=true, or scheduler.enabled=false.")
if _browser_tools_enabled_in_config(config):
raise SystemExit(browser_multi_worker_error(workers))
if backend != "postgres":
raise SystemExit(f"GATEWAY_WORKERS={workers} requires database.backend='postgres', but database.backend is '{backend}'. SQLite cannot support concurrent multi-process access. Set GATEWAY_WORKERS=1 or switch to Postgres.")
if run_events_backend != "db":View on GitHub (pinned to 1dd6ba1acb)
Solutions
- Set database.backend: postgres (with a valid postgres URL) in config.yaml
- Or set scheduler.multi_instance: false if running a single instance
- Then restart the Gateway and verify it boots
Example fix
# config.yaml # before database: backend: sqlite scheduler: multi_instance: true # after database: backend: postgres url: postgresql+asyncpg://user:pass@host/deerflow scheduler: multi_instance: true
Defensive patterns
Strategy: validation
Validate before calling
# Preflight before launching multi-instance scheduler mode from app.config import load_config cfg = load_config() assert not (getattr(getattr(cfg, "scheduler", None), "multi_instance", False) and cfg.database.backend != "postgres"), "multi_instance needs postgres"
Prevention
- Run a config preflight (make doctor / config validation) in CI for every environment's config.yaml
- Treat scheduler.multi_instance as a bundle: postgres + run_events db + heartbeats
- Keep dev (sqlite) and prod (postgres) configs in separate checked templates so flags don't leak across
When it happens
Trigger: config.yaml sets scheduler.multi_instance: true (checked regardless of scheduler.enabled) while database.backend is sqlite or memory; or GATEWAY_WORKERS>1 with multi_instance set but the DB was left on sqlite.
Common situations: Scaling a single-node sqlite deployment out to multiple workers/replicas; copying config between environments (dev sqlite vs prod postgres) without flipping the database backend.
Related errors
- scheduler.multi_instance=true requires run_events.backend='d
- scheduler.multi_instance=true requires run_ownership.heartbe
- GATEWAY_WORKERS={workers} cannot run with scheduler.enabled=
- GATEWAY_WORKERS={workers} requires database.backend='postgre
- GATEWAY_WORKERS={workers} cannot enable agentic browser tool
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/4453d44e05f89824.
Report an issue: GitHub.