{"record":{"id":"536dd63ffd53f2db","repo":"OpenBB-finance/OpenBB","slug":"maturity-must-be-between-1-and-100","errorCode":null,"errorMessage":"Maturity must be between 1 and 100","messagePattern":"Maturity must be between 1 and 100","errorType":"exception","errorClass":"OpenBBError","httpStatus":null,"severity":"error","filePath":"openbb_platform/providers/fred/openbb_fred/models/spot.py","lineNumber":79,"sourceCode":"    ) -> list:\n        \"\"\"Extract data.\"\"\"\n        # pylint: disable=import-outside-toplevel\n        from openbb_fred.utils.fred_base import Fred\n        from openbb_fred.utils.fred_helpers import (\n            comma_to_float_list,\n            get_spot_series_id,\n        )\n\n        key = credentials.get(\"fred_api_key\") if credentials else \"\"\n        fred = Fred(key)\n\n        maturity = (\n            comma_to_float_list(query.maturity)\n            if isinstance(query.maturity, str)\n            else [query.maturity]\n        )\n        if any(1 > m > 100 for m in maturity):\n            raise OpenBBError(\"Maturity must be between 1 and 100\")\n\n        series = get_spot_series_id(\n            maturity=maturity,\n            category=query.category.split(\",\"),\n        )\n\n        data = []\n\n        for s in series:\n            id_ = s[\"FRED Series ID\"]\n            title = s[\"Title\"]\n            d = fred.get_series(\n                series_id=id_,\n                start_date=query.start_date,\n                end_date=query.end_date,\n                **kwargs,\n            )\n            for item in d:","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/OpenBB-finance/OpenBB/blob/3e071fcc2cd9f891cac6040ae60296dba76dab46/openbb_platform/providers/fred/openbb_fred/models/spot.py#L61-L97","documentation":"Intended as a range check in FredSpotFetcher.extract_data (openbb_fred/models/spot.py:79): maturity values (years) must lie in [1, 100] before mapping to FRED spot-rate series IDs. IMPORTANT: the guard as written, 'if any(1 > m > 100 for m in maturity)', is a chained comparison meaning (1 > m) and (m > 100), which is unsatisfiable - so this OpenBBError can never actually fire. Out-of-range maturities therefore fall through to get_spot_series_id, which returns an empty series list and the call fails elsewhere (or returns empty data) instead.","triggerScenarios":"Passing maturity=0, maturity=150, or a comma list like '2,120' - the intended triggers, but due to the chained-comparison bug the error is NOT raised; the observable symptom becomes an empty result or empty-data error from the downstream series lookup, not this message.","commonSituations":"Porting UIs that let users type arbitrary tenors; unit tests asserting this message fires for maturity=200 and mysteriously failing; code review flags after upgrading Python versions where chained comparisons behave identically (they always did - the bug is logical).","solutions":["Fix the provider condition to 'if any(m < 1 or m > 100 for m in maturity)' (or 'not 1 <= m <= 100').","Until patched, validate maturities client-side before calling the endpoint.","File/track an upstream issue on the OpenBB repo referencing openbb_fred/models/spot.py:78."],"exampleFix":"# before (openbb_fred/models/spot.py:78) - condition can never be true\nif any(1 > m > 100 for m in maturity):\n    raise OpenBBError(\"Maturity must be between 1 and 100\")\n\n# after\nif any(m < 1 or m > 100 for m in maturity):\n    raise OpenBBError(\"Maturity must be between 1 and 100\")","handlingStrategy":"validation","validationCode":"def validate_maturities(maturity: int | float | str) -> list[float]:\n    ms = [float(m) for m in str(maturity).split(',')] if isinstance(maturity, str) else [float(maturity)]\n    bad = [m for m in ms if not (1 <= m <= 100)]\n    if bad:\n        raise ValueError(f'Maturity out of range [1, 100]: {bad}')\n    return ms\n\nvalidate_maturities(maturity)  # call BEFORE obb.economy.fred.spot(...)","typeGuard":"def is_valid_maturity(m: object) -> bool:\n    \"\"\"True when m is a number in the FRED spot-rate maturity range [1, 100].\"\"\"\n    return isinstance(m, (int, float)) and not isinstance(m, bool) and 1 <= m <= 100","tryCatchPattern":null,"preventionTips":["Validate the range client-side - the provider guard at spot.py:78 is dead code ('1 > m > 100' is unsatisfiable) and never raises.","Constrain UI inputs for tenor to the values FRED actually publishes.","Track the upstream fix; add a regression test asserting the guard fires for maturity=0 and maturity=150."],"tags":["fred","spot-rates","maturity","validation","logic-bug"],"backgroundTag":null,"analyzedSha":"3e071fcc2cd9f891cac6040ae60296dba76dab46","analyzedAt":"2026-08-14T23:40:48.960Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}