zylon-ai/private-gpt · critical · ValueError

Unsupported scheduler.tools.mode=

Error message

Unsupported scheduler.tools.mode={self.scheduler.tools.mode!r}. Supported tool scheduler modes are 'local' and 'celery'.

What it means

Startup-time ValueError from the root Settings model_validator: scheduler.tools.mode must be 'local' or 'celery'. The tools scheduler decides whether tool executions run in-process or are dispatched through Celery; any other value (including chat-side values like 'arq') fails settings validation at boot.

Solutions

  1. Set scheduler.tools.mode to 'local' or 'celery' as intended.
  2. If you configured 'arq' for tools, that is chat-only — choose 'celery' for distributed tool execution (and set chat mode to 'arq').
  3. Sweep every config source (profile YAMLs, env vars, deployment overlays) for the key.
  4. Restart after fixing; validation runs at import/startup time.

Example fix

# before
scheduler:
  tools:
    mode: arq
# after
scheduler:
  tools:
    mode: celery
  # remember: tools=celery requires chat mode 'arq'
Defensive patterns

Strategy: validation

Validate before calling

mode = cfg.get('scheduler', {}).get('tools', {}).get('mode')
assert mode in {'local', 'celery'}, f'bad scheduler.tools.mode: {mode!r}'

Type guard

const isToolsMode = (m: unknown): m is 'local' | 'celery' => m === 'local' || m === 'celery';

Prevention

When it happens

Trigger: settings.yaml with scheduler.tools.mode: arq (wrong side — arq belongs to chat), 'redis', or a typo; env var override left from a previous schema; mirroring the chat mode value into tools because they 'should match'.

Common situations: Operators assuming one scheduler mode for everything; version upgrades that split a single scheduler key into chat/tools; helm values or dotenv overlays not updated alongside the main YAML.

Related errors


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/64f31ebb9f88043b. Report an issue: GitHub.

Appendix: source

Thrown at private_gpt/settings/settings.py:1872

    brave: BraveSearchSettings
    skills: SkillSettings
    transformation: TransformationSettings
    semaphore: SemaphoreSettings
    scheduler: SchedulerConfig = Field(
        default_factory=SchedulerConfig,
        description="Scheduler configuration for chat and tool workers.",
    )

    @model_validator(mode="after")
    def validate_chat_scheduler_configuration(self) -> "Settings":
        if self.scheduler.chat.mode not in {"local", "arq"}:
            raise ValueError(
                f"Unsupported scheduler.chat.mode={self.scheduler.chat.mode!r}. "
                "Supported chat scheduler modes are 'local' and 'arq'."
            )

        if self.scheduler.tools.mode not in {"local", "celery"}:
            raise ValueError(
                f"Unsupported scheduler.tools.mode={self.scheduler.tools.mode!r}. "
                "Supported tool scheduler modes are 'local' and 'celery'."
            )

        if self.scheduler.tools.mode == "celery" and self.scheduler.chat.mode != "arq":
            raise ValueError(
                f"scheduler.tools.mode={self.scheduler.tools.mode!r} requires "
                "scheduler.chat.mode='arq' so tool callbacks can resume shared "
                "chat state."
            )

        if self.scheduler.chat.mode == "local":
            return self

        if self.stream.broker != "redis":
            raise ValueError(
                f"scheduler.chat.mode={self.scheduler.chat.mode!r} requires stream.broker=redis "
                "because API and chat worker processes must share stream state."

View on GitHub (pinned to 4a030776a3)