zylon-ai/private-gpt · critical · ValueError

Unsupported scheduler.tools.mode={self.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.

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)

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.