{"record":{"id":"2120f25fd604da45","repo":"OpenBB-finance/OpenBB","slug":"invalid-signal-v-available-signals-are-sign","errorCode":null,"errorMessage":"Invalid signal '{v}'. Available signals are:\n{SIGNALS_DESC_STR}","messagePattern":"Invalid signal '(.+?)'\\. Available signals are:\n(.+?)","errorType":"validation","errorClass":"OpenBBError","httpStatus":null,"severity":"error","filePath":"openbb_platform/providers/finviz/openbb_finviz/models/equity_screener.py","lineNumber":130,"sourceCode":"    )\n    filters_dict: dict | str | None = Field(\n        default=None,\n        kw_only=True,\n        description=\"A formatted dictionary, or serialized JSON string, of additional filters to apply to the query.\"\n        + \" This parameter can be used as an alternative to preset files, and is ignored when a preset is supplied.\"\n        + \" Invalid entries will raise an error. Syntax should follow the 'screener_template.ini' file.\",\n    )\n    limit: int | None = Field(\n        default=None,\n        description=QUERY_DESCRIPTIONS.get(\"limit\", \"\"),\n    )\n\n    @field_validator(\"signal\", mode=\"before\", check_fields=False)\n    @classmethod\n    def validate_signal(cls, v):\n        \"\"\"Validate the signal.\"\"\"\n        if v is not None and v not in SIGNALS:\n            raise OpenBBError(\n                f\"Invalid signal '{v}'. Available signals are:\\n{SIGNALS_DESC_STR}\"\n            )\n        return v if v else None\n\n    @field_validator(\"industry\", mode=\"before\", check_fields=False)\n    @classmethod\n    def validate_industry(cls, v):\n        \"\"\"Validate the industry.\"\"\"\n        if v is not None and v not in INDUSTRY_MAP:\n            raise OpenBBError(\n                f\"Invalid industry '{v}'. Available industries are:\\n{', '.join(INDUSTRY_MAP)}\"\n            )\n        return v if v else None\n\n    @field_validator(\"preset\", mode=\"before\", check_fields=False)\n    @classmethod\n    def validate_preset(cls, v):\n        \"\"\"Check to reject running template file.\"\"\"","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/OpenBB-finance/OpenBB/blob/3e071fcc2cd9f891cac6040ae60296dba76dab46/openbb_platform/providers/finviz/openbb_finviz/models/equity_screener.py#L112-L148","documentation":"Finviz equity screener query params validator rejects the `signal` field when its value is not a key of the SIGNALS mapping. The error message enumerates every valid signal via SIGNALS_DESC_STR. This fires at query-model construction time (pydantic field_validator, mode='before'), before any network call.","triggerScenarios":"Passing signal='Top Gainers' or any free-text not in SIGNALS; case or spelling mismatches ('top_gainers' vs 'Top Gainers'); passing an empty string (coerced to None, which is allowed) vs a wrong non-empty string.","commonSituations":"Porting signal names from another provider's vocabulary; user-supplied signal strings from a config file or CLI that were never checked against the Finviz signal list.","solutions":["Use a signal name exactly as listed in SIGNALS_DESC_STR in the error output","Validate user input against openbb_finviz.utils.reference_data.SIGNALS before building the query","Normalize input (strip/casefold) and map it to the canonical Finviz signal name"],"exampleFix":"# before\nq = FinvizEquityScreenerQueryParams(signal=\"top gainers\")  # wrong casing -> OpenBBError\n\n# after\nfrom openbb_finviz.utils.reference_data import SIGNALS\nsig = next((s for s in SIGNALS if s.casefold() == user_input.casefold()), None)\nif sig is None:\n    raise ValueError(f\"unknown signal: {user_input}\")\nq = FinvizEquityScreenerQueryParams(signal=sig)","handlingStrategy":"validation","validationCode":"from openbb_finviz.utils.reference_data import SIGNALS\n\nif signal is not None and signal not in SIGNALS:\n    raise ValueError(f\"Pick one of: {', '.join(SIGNALS)}\")\nq = FinvizEquityScreenerQueryParams(signal=signal)","typeGuard":"def is_valid_signal(v: str | None) -> bool:\n    return v is None or v in SIGNALS","tryCatchPattern":"from openbb_core.app.model.obb_error import OpenBBError\n\ntry:\n    q = FinvizEquityScreenerQueryParams(signal=signal)\nexcept OpenBBError as e:\n    # message already enumerates valid signals; surface to user input form\n    raise HTTPException(400, str(e)) from e","preventionTips":["Derive signal choices for UIs/configs from SIGNALS, never hard-code","Normalize casing before passing","Treat validation errors as user-input bugs, not transient failures — do not retry"],"tags":["openbb","finviz","validation","screener","signal"],"backgroundTag":null,"analyzedSha":"3e071fcc2cd9f891cac6040ae60296dba76dab46","analyzedAt":"2026-08-14T23:40:48.960Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}