harry0703/MoneyPrinterTurbo · error · ValueError

video_terms must be a string or a list of strings.

Error message

video_terms must be a string or a list of strings.

What it means

Raised in the task script pipeline when params.video_terms is neither a str nor a list. The value may be a comma or Chinese-comma separated string (split into terms) or a list (entries stripped), but any other type (None from an omitted-yet-present JSON key, a number, a dict) fails fast with this ValueError rather than silently producing no search terms.

Source

Thrown at app/services/task.py:308

    logger.info("\n\n## generating video terms")
    video_terms = params.video_terms
    if not video_terms:
        # 开启素材按文案顺序匹配后,关键词本身也必须按脚本叙事顺序生成;
        # 否则后续即使顺序下载和顺序拼接,也只能复用一组全局主题词,
        # 无法改善“后面内容的画面提前出现”的问题。
        video_terms = llm.generate_terms(
            video_subject=params.video_subject,
            video_script=video_script,
            amount=8 if params.match_materials_to_script else 5,
            match_script_order=params.match_materials_to_script,
        )
    else:
        if isinstance(video_terms, str):
            video_terms = [term.strip() for term in re.split(r"[,,]", video_terms)]
        elif isinstance(video_terms, list):
            video_terms = [term.strip() for term in video_terms]
        else:
            raise ValueError("video_terms must be a string or a list of strings.")

        logger.debug(f"video terms: {utils.to_json(video_terms)}")

    if not video_terms:
        _mark_task_failed(
            task_id,
            "terms",
            "failed to generate video search terms",
        )
        return None

    # 可选的 TwelveLabs Marengo 语义重排:未启用时返回原顺序,无任何副作用。
    # 顺序匹配模式下关键词顺序本身就是脚本叙事顺序,必须保持原样,故跳过。
    if not params.match_materials_to_script:
        video_terms = twelvelabs.rerank_terms_by_subject(
            video_subject=params.video_subject,
            search_terms=video_terms,
        )

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Fix the caller: send video_terms as a string or a list of strings, or omit the field entirely so LLM generation is used.
  2. If the value comes from user input, coerce before task creation and treat null as omitted.
  3. Add request-schema validation (pydantic or jsonschema) at the API boundary so this fails with a 422 naming the field, not a mid-task ValueError.
  4. Inspect the task params JSON on disk to see what was actually stored.

Example fix

# before
task_params = {"video_subject": "cats", "video_terms": None}
# after (omit the key to use LLM generation, or pass a valid type)
task_params = {"video_subject": "cats"}
# or: {"video_subject": "cats", "video_terms": ["cats", "kittens"]}
Defensive patterns

Strategy: type-guard

Validate before calling

# validate at the API boundary before task creation
def validate_video_terms(value: object) -> None:
    if isinstance(value, str):
        return
    if isinstance(value, list) and all(isinstance(t, str) for t in value):
        return
    raise HTTPException(422, "video_terms must be a string or list of strings")

Type guard

def is_valid_video_terms(value: object) -> bool:
    if isinstance(value, str):
        return True
    if isinstance(value, list):
        return all(isinstance(term, str) for term in value)
    return False

Try / catch

try:
    terms = get_video_terms(params)
except ValueError as exc:
    if "video_terms must be" in str(exc):
        fail_task_with_user_visible_reason(params, str(exc))
    raise

Prevention

When it happens

Trigger: Task creation called with video_terms null, a number, or an object in the JSON payload; a client form serializing an empty input as null instead of omitting the field; script callers passing a sentinel value like 0.

Common situations: Frontend sends null for an optional field it should omit; API consumers building payloads dynamically and defaulting to None; schema drift where a client assumed an object wrapper.

Related errors


AI-assisted analysis of harry0703/MoneyPrinterTurbo@1f9f19c202 (2026-08-14). Data as JSON: /api/errors/a6c7f11df80bab4c. Report an issue: GitHub.