ruvnet/RuView · error · ValueError

Log level must be one of: {allowed_levels}

Error message

Log level must be one of: {allowed_levels}

What it means

Pydantic v2 @field_validator on Settings.log_level in archive/v1/src/config/settings.py. It uppercases the input and enforces membership in ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']. The check is case-insensitive (v.upper()), but aliases are not supported: 'TRACE', 'NOTICE', 'VERBOSE', and notably 'WARN' — a legal alias in Python's own logging module — are all rejected with this ValueError at Settings() construction.

Source

Thrown at archive/v1/src/config/settings.py:191

        extra="ignore",
    )
    
    @field_validator("environment")
    @classmethod
    def validate_environment(cls, v):
        """Validate environment setting."""
        allowed_environments = ["development", "staging", "production"]
        if v not in allowed_environments:
            raise ValueError(f"Environment must be one of: {allowed_environments}")
        return v
    
    @field_validator("log_level")
    @classmethod
    def validate_log_level(cls, v):
        """Validate log level setting."""
        allowed_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
        if v.upper() not in allowed_levels:
            raise ValueError(f"Log level must be one of: {allowed_levels}")
        return v.upper()
    
    @field_validator("pose_confidence_threshold")
    @classmethod
    def validate_confidence_threshold(cls, v):
        """Validate confidence threshold."""
        if not 0.0 <= v <= 1.0:
            raise ValueError("Confidence threshold must be between 0.0 and 1.0")
        return v
    
    @field_validator("stream_fps")
    @classmethod
    def validate_stream_fps(cls, v):
        """Validate streaming FPS."""
        if not 1 <= v <= 60:
            raise ValueError("Stream FPS must be between 1 and 60")
        return v
    

View on GitHub (pinned to 4685618388)

Solutions

  1. Use the full standard names: DEBUG, INFO, WARNING, ERROR, or CRITICAL (case does not matter)
  2. Replace WARN with WARNING everywhere (docker-compose, .env, k8s env blocks)
  3. Map exotic levels at the source: TRACE->DEBUG, NOTICE->INFO
  4. Add a startup config check in CI to catch bad LOG_LEVEL values before deploy

Example fix

# before
LOG_LEVEL=WARN

# after
LOG_LEVEL=WARNING
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED = {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"}
raw = os.environ.get("LOG_LEVEL", "INFO").strip().upper()
normalized = {"WARN": "WARNING", "TRACE": "DEBUG", "VERBOSE": "DEBUG", "NOTICE": "INFO"}.get(raw, raw)
assert normalized in ALLOWED, f"LOG_LEVEL must be one of {sorted(ALLOWED)}, got {raw!r}"

Type guard

def is_valid_log_level(v: str) -> bool:
    return v.strip().upper() in {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"}

Try / catch

from pydantic import ValidationError
try:
    settings = Settings()
except ValidationError as e:
    if any(err["loc"][-1] == "log_level" for err in e.errors()):
        raise SystemExit("LOG_LEVEL: use DEBUG|INFO|WARNING|ERROR|CRITICAL (WARN alias is rejected)") from e
    raise

Prevention

When it happens

Trigger: LOG_LEVEL=WARN (legal in logging.basicConfig but rejected here); LOG_LEVEL=TRACE or VERBOSE from structured-logging conventions; LOG_LEVEL=notice; lowercase 'debug' works (uppercased), but any non-standard name fails.

Common situations: Copying LOG_LEVEL=WARN from systemd or logging tutorials; switching from loguru (TRACE) back to stdlib settings; operators shortening WARNING to WARN in .env files.

Related errors


AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16). Data as JSON: /api/errors/2e7f004343acebf7. Report an issue: GitHub.