datawhalechina/hello-agents · error · ValueError

Unsupported quality_mode: {quality_mode}

Error message

Unsupported quality_mode: {quality_mode}

What it means

`_resolve_quality_mode` enforces the three-level output-quality enum {'draft', 'standard', 'publication'} for analysis runs, raising ValueError on anything else after strip+lowercase. quality_mode drives chart polish and how many review iterations (`_default_max_reviews_for_mode`) the agent performs.

Source

Thrown at Co-creation-projects/healer-666-Academic-Data-Agent/src/data_analysis_agent/agent_runner.py:640

    for directory in (data_dir, figures_dir, logs_dir):
        directory.mkdir(parents=True, exist_ok=True)
    return run_dir, data_dir, figures_dir, logs_dir


def _build_run_context_text(run_dir: Path, cleaned_data_path: Path, figures_dir: Path, logs_dir: Path) -> str:
    return (
        f"\n本次任务的专属输出根目录为:{run_dir.as_posix()}\n"
        f"清洗后的数据必须保存到:{cleaned_data_path.as_posix()}\n"
        f"所有图表必须保存到:{figures_dir.as_posix()}\n"
        f"运行轨迹与日志目录为:{logs_dir.as_posix()}\n"
        "请务必严格遵守“先清洗落盘,再重读分析”的两阶段流水线。\n"
    )


def _resolve_quality_mode(quality_mode: str) -> str:
    normalized_mode = quality_mode.strip().lower()
    if normalized_mode not in {"draft", "standard", "publication"}:
        raise ValueError(f"Unsupported quality_mode: {quality_mode}")
    return normalized_mode


def _should_attempt_vision_review(*, quality_mode: str, review_enabled: bool, vision_review_mode: str) -> bool:
    if not review_enabled or vision_review_mode == "off":
        return False
    if vision_review_mode == "on":
        return quality_mode in {"standard", "publication"}
    return quality_mode == "publication"


def _default_max_reviews_for_mode(quality_mode: str) -> int:
    mapping = {
        "draft": 0,
        "standard": 1,
        "publication": 2,
    }
    return mapping[quality_mode]

View on GitHub (pinned to 606a07d341)

Solutions

  1. Send exactly 'draft', 'standard', or 'publication' (case/whitespace tolerant).
  2. Sync frontend option lists to the backend enum; ideally define the enum in one shared place.
  3. Omit the field for the default rather than passing None.
  4. Harden the resolver with a None/empty fallback to 'standard'.

Example fix

// before
normalized_mode = quality_mode.strip().lower()
if normalized_mode not in {"draft", "standard", "publication"}:
    raise ValueError(f"Unsupported quality_mode: {quality_mode}")

# after
normalized_mode = (quality_mode or "standard").strip().lower()
if normalized_mode not in {"draft", "standard", "publication"}:
    raise ValueError(f"Unsupported quality_mode: {quality_mode}")
Defensive patterns

Strategy: type-guard

Validate before calling

QUALITY_MODES = {"draft", "standard", "publication"}

def validate_quality_mode(mode: str | None) -> str:
    normalized = (mode or "standard").strip().lower()
    if normalized not in QUALITY_MODES:
        raise ValueError(f"quality_mode must be one of {sorted(QUALITY_MODES)}, got {mode!r}")
    return normalized

Type guard

from typing import Literal, TypeGuard

QualityMode = Literal["draft", "standard", "publication"]

def is_quality_mode(value: object) -> TypeGuard[QualityMode]:
    return isinstance(value, str) and value.strip().lower() in {"draft", "standard", "publication"}

Try / catch

try:
    run_analysis(data_path, quality_mode=qm)
except ValueError as e:
    if "quality_mode" in str(e):
        qm = "standard"
        run_analysis(data_path, quality_mode=qm)
    else:
        raise

Prevention

When it happens

Trigger: Passing quality_mode='high', 'pub', 'final', 'STANDARD ' is fine (normalized) but 'publish'/'normal' fail; None crashes on `.strip()`; a UI dropdown desynchronized from the backend enum sends a stale value.

Common situations: Frontend/backend enum drift after a release renames modes, user-typed config values, or scripts written against an older API that accepted different quality levels.

Related errors


AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14). Data as JSON: /api/errors/1f47dddb75bcc211. Report an issue: GitHub.