{"record":{"id":"1f47dddb75bcc211","repo":"datawhalechina/hello-agents","slug":"unsupported-quality-mode-quality-mode","errorCode":null,"errorMessage":"Unsupported quality_mode: {quality_mode}","messagePattern":"Unsupported quality_mode: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Co-creation-projects/healer-666-Academic-Data-Agent/src/data_analysis_agent/agent_runner.py","lineNumber":640,"sourceCode":"    for directory in (data_dir, figures_dir, logs_dir):\n        directory.mkdir(parents=True, exist_ok=True)\n    return run_dir, data_dir, figures_dir, logs_dir\n\n\ndef _build_run_context_text(run_dir: Path, cleaned_data_path: Path, figures_dir: Path, logs_dir: Path) -> str:\n    return (\n        f\"\\n本次任务的专属输出根目录为：{run_dir.as_posix()}\\n\"\n        f\"清洗后的数据必须保存到：{cleaned_data_path.as_posix()}\\n\"\n        f\"所有图表必须保存到：{figures_dir.as_posix()}\\n\"\n        f\"运行轨迹与日志目录为：{logs_dir.as_posix()}\\n\"\n        \"请务必严格遵守“先清洗落盘，再重读分析”的两阶段流水线。\\n\"\n    )\n\n\ndef _resolve_quality_mode(quality_mode: str) -> str:\n    normalized_mode = quality_mode.strip().lower()\n    if normalized_mode not in {\"draft\", \"standard\", \"publication\"}:\n        raise ValueError(f\"Unsupported quality_mode: {quality_mode}\")\n    return normalized_mode\n\n\ndef _should_attempt_vision_review(*, quality_mode: str, review_enabled: bool, vision_review_mode: str) -> bool:\n    if not review_enabled or vision_review_mode == \"off\":\n        return False\n    if vision_review_mode == \"on\":\n        return quality_mode in {\"standard\", \"publication\"}\n    return quality_mode == \"publication\"\n\n\ndef _default_max_reviews_for_mode(quality_mode: str) -> int:\n    mapping = {\n        \"draft\": 0,\n        \"standard\": 1,\n        \"publication\": 2,\n    }\n    return mapping[quality_mode]","sourceCodeStart":622,"sourceCodeEnd":658,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/healer-666-Academic-Data-Agent/src/data_analysis_agent/agent_runner.py#L622-L658","documentation":"`_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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Send exactly 'draft', 'standard', or 'publication' (case/whitespace tolerant).","Sync frontend option lists to the backend enum; ideally define the enum in one shared place.","Omit the field for the default rather than passing None.","Harden the resolver with a None/empty fallback to 'standard'."],"exampleFix":"// before\nnormalized_mode = quality_mode.strip().lower()\nif normalized_mode not in {\"draft\", \"standard\", \"publication\"}:\n    raise ValueError(f\"Unsupported quality_mode: {quality_mode}\")\n\n# after\nnormalized_mode = (quality_mode or \"standard\").strip().lower()\nif normalized_mode not in {\"draft\", \"standard\", \"publication\"}:\n    raise ValueError(f\"Unsupported quality_mode: {quality_mode}\")","handlingStrategy":"type-guard","validationCode":"QUALITY_MODES = {\"draft\", \"standard\", \"publication\"}\n\ndef validate_quality_mode(mode: str | None) -> str:\n    normalized = (mode or \"standard\").strip().lower()\n    if normalized not in QUALITY_MODES:\n        raise ValueError(f\"quality_mode must be one of {sorted(QUALITY_MODES)}, got {mode!r}\")\n    return normalized","typeGuard":"from typing import Literal, TypeGuard\n\nQualityMode = Literal[\"draft\", \"standard\", \"publication\"]\n\ndef is_quality_mode(value: object) -> TypeGuard[QualityMode]:\n    return isinstance(value, str) and value.strip().lower() in {\"draft\", \"standard\", \"publication\"}","tryCatchPattern":"try:\n    run_analysis(data_path, quality_mode=qm)\nexcept ValueError as e:\n    if \"quality_mode\" in str(e):\n        qm = \"standard\"\n        run_analysis(data_path, quality_mode=qm)\n    else:\n        raise","preventionTips":["Single-source the enum (shared schema/constant) across client, server, and docs.","Add schema validation (pydantic Literal fields) at the request boundary.","Regression-test the enum set when renaming modes in releases."],"tags":["validation","enum","valueerror","configuration","python"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}