{"record":{"id":"9cf03c8fbb72b810","repo":"HKUDS/Vibe-Trading","slug":"field-name-must-be-a-non-empty-array-of-kind-lab","errorCode":null,"errorMessage":"{field_name} must be a non-empty array of kind labels","messagePattern":"(.+?) must be a non-empty array of kind labels","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/cashflow_analytics_tool.py","lineNumber":443,"sourceCode":"\n\ndef _coerce_kinds(raw: Any, field_name: str) -> list[str] | None:\n    \"\"\"Validate an optional kind-classification override.\n\n    Args:\n        raw: Value supplied for ``external_kinds`` or ``internal_kinds``.\n        field_name: Name used in the error message.\n\n    Returns:\n        The list of labels, or ``None`` to keep the module default.\n\n    Raises:\n        ValueError: If the value is not an array of non-empty strings.\n    \"\"\"\n    if raw is None:\n        return None\n    if not isinstance(raw, list) or not raw:\n        raise ValueError(f\"{field_name} must be a non-empty array of kind labels\")\n    labels: list[str] = []\n    for item in raw:\n        if not isinstance(item, str) or not item.strip():\n            raise ValueError(f\"{field_name} entries must be non-empty strings\")\n        labels.append(item)\n    return labels\n\n\ndef _rounded(value: float) -> float:\n    \"\"\"Round a finite scalar for stable, compact JSON.\n\n    Args:\n        value: Number to round.\n\n    Returns:\n        The value rounded to :data:`_ROUNDING` decimal places.\n    \"\"\"\n    return round(float(value), _ROUNDING)","sourceCodeStart":425,"sourceCodeEnd":461,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/cashflow_analytics_tool.py#L425-L461","documentation":"The filter fields accepted by _coerce_kinds (e.g. include_kinds/exclude_kinds) must be a non-empty list of strings when provided. An empty list, a scalar, a tuple, or any other non-list value is rejected because an empty filter is ambiguous (no filtering vs filter-everything).","triggerScenarios":"Passing include_kinds=[] (empty list), include_kinds=\"dividend\" (bare string), or a tuple/set instead of a list; None is allowed and means 'no filter'.","commonSituations":"Dynamically building filters that end up empty after filtering; spreading a possibly-empty sequence from user input; assuming any iterable is accepted.","solutions":["Pass None (or omit the argument) when no kind filtering is wanted","Ensure the value is a Python list with at least one non-empty label string, e.g. [\"dividend\"]","Coerce tuples/sets to list(...) before calling"],"exampleFix":"# before\nexecute(flows=flows, include_kinds=[])\n# after\nexecute(flows=flows, include_kinds=None)\n# or\nexecute(flows=flows, include_kinds=[\"coupon\"])","handlingStrategy":"type-guard","validationCode":"def norm_kinds(field_name, v):\n    if v is None:\n        return None\n    if not isinstance(v, list) or not v:\n        raise TypeError(f\"{field_name} must be a non-empty list or None\")\n    return v","typeGuard":"def is_kinds_list(v) -> bool:\n    return v is None or (isinstance(v, list) and len(v) > 0)","tryCatchPattern":"try:\n    execute(flows=flows, include_kinds=kinds)\nexcept ValueError as exc:\n    if \"must be a non-empty array\" in str(exc):\n        execute(flows=flows, include_kinds=None)  # drop the filter\n    else:\n        raise","preventionTips":["Treat an empty filter as 'no filter': convert falsy lists to None before calling","list(...) any tuple/set before passing","Unit-test boundary cases (empty list, scalar) in wrappers around the tool"],"tags":["validation","list","cashflow","python"],"backgroundTag":"empty-collection-argument","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}