datawhalechina/hello-agents · error · ValueError

Unsupported vision_review_mode: {vision_review_mode}

Error message

Unsupported vision_review_mode: {vision_review_mode}

What it means

`_resolve_vision_review_mode` validates the vision_review_mode option after strip+lowercase and raises ValueError unless it is 'off', 'auto', or 'on'. This option controls whether the agent runs an optional vision-LLM review pass over generated charts.

Source

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

                parts.append(f"... {len(results) - 3} more result(s) omitted.")
        return "\n\n".join(parts)

    if text:
        parts.append(f"Observation text:\n{_truncate_text(text, 1200)}")
    return "\n\n".join(parts)


def _resolve_latency_mode(latency_mode: str) -> str:
    normalized_mode = latency_mode.strip().lower()
    if normalized_mode not in {"auto", "quality", "fast"}:
        raise ValueError(f"Unsupported latency_mode: {latency_mode}")
    return normalized_mode


def _resolve_vision_review_mode(vision_review_mode: str) -> str:
    normalized_mode = vision_review_mode.strip().lower()
    if normalized_mode not in {"off", "auto", "on"}:
        raise ValueError(f"Unsupported vision_review_mode: {vision_review_mode}")
    return normalized_mode


def _is_small_simple_dataset(data_context: DataContextSummary) -> bool:
    try:
        file_size_bytes = data_context.absolute_path.stat().st_size
    except OSError:
        file_size_bytes = 0
    rows, cols = data_context.shape
    return file_size_bytes <= 512 * 1024 and rows <= 2000 and cols <= 50


def _should_use_fast_path(latency_mode: str, *, small_simple_dataset: bool) -> bool:
    return latency_mode == "fast" or (latency_mode == "auto" and small_simple_dataset)


def _resolve_effective_max_steps(
    *,

View on GitHub (pinned to 606a07d341)

Solutions

  1. Use exactly 'off', 'auto', or 'on' (case-insensitive, whitespace trimmed).
  2. Map boolean flags to the enum client-side: True→'on', False→'off'.
  3. Omit the parameter if you want the default instead of sending None.
  4. Harden: `normalized_mode = (vision_review_mode or 'auto').strip().lower()`.

Example fix

// before
normalized_mode = vision_review_mode.strip().lower()
if normalized_mode not in {"off", "auto", "on"}:
    raise ValueError(f"Unsupported vision_review_mode: {vision_review_mode}")

# after
normalized_mode = (vision_review_mode or "auto").strip().lower()
if normalized_mode not in {"off", "auto", "on"}:
    raise ValueError(f"Unsupported vision_review_mode: {vision_review_mode}")
Defensive patterns

Strategy: type-guard

Validate before calling

VISION_REVIEW_MODES = {"off", "auto", "on"}

def validate_vision_mode(mode: str | None) -> str:
    normalized = (mode or "auto").strip().lower()
    assert normalized in VISION_REVIEW_MODES, f"vision_review_mode must be one of {sorted(VISION_REVIEW_MODES)}"
    return normalized

Type guard

from typing import Literal, TypeGuard

VisionReviewMode = Literal["off", "auto", "on"]

def is_vision_review_mode(value: object) -> TypeGuard[VisionReviewMode]:
    return isinstance(value, str) and value.strip().lower() in {"off", "auto", "on"}

Try / catch

try:
    run_analysis(data_path, vision_review_mode=mode)
except ValueError as e:
    if "vision_review_mode" in str(e):
        mode = "auto"
        run_analysis(data_path, vision_review_mode=mode)
    else:
        raise

Prevention

When it happens

Trigger: Calling the run API with vision_review_mode='enabled', 'true', 'always', or an empty string; passing None causes AttributeError on `.strip()` before the enum check fires.

Common situations: Booleans serialized as 'true'/'false' strings by JSON clients; hand-edited config YAML with mode names from older versions; API consumers guessing allowed values without reading the enum.

Related errors


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