{"record":{"id":"ec629becf66ac95e","repo":"TheAlgorithms/Python","slug":"number-of-years-must-be-0","errorCode":null,"errorMessage":"number_of_years must be > 0","messagePattern":"number_of_years must be > 0","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"financial/interest.py","lineNumber":106,"sourceCode":"    >>> apr_interest(10000.0, 0.05, 1)\n    512.6749646744732\n    >>> apr_interest(0.5, 0.05, 3)\n    0.08091115361317736\n    >>> apr_interest(10000.0, 0.06, -4)\n    Traceback (most recent call last):\n        ...\n    ValueError: number_of_years must be > 0\n    >>> apr_interest(10000.0, -3.5, 3.0)\n    Traceback (most recent call last):\n        ...\n    ValueError: nominal_annual_percentage_rate must be >= 0\n    >>> apr_interest(-5500.0, 0.01, 5)\n    Traceback (most recent call last):\n        ...\n    ValueError: principal must be > 0\n    \"\"\"\n    if number_of_years <= 0:\n        raise ValueError(\"number_of_years must be > 0\")\n    if nominal_annual_percentage_rate < 0:\n        raise ValueError(\"nominal_annual_percentage_rate must be >= 0\")\n    if principal <= 0:\n        raise ValueError(\"principal must be > 0\")\n\n    return compound_interest(\n        principal, nominal_annual_percentage_rate / 365, number_of_years * 365\n    )\n\n\nif __name__ == \"__main__\":\n    import doctest\n\n    doctest.testmod()\n","sourceCodeStart":88,"sourceCodeEnd":121,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/financial/interest.py#L88-L121","documentation":"Raised by apr_interest() in financial/interest.py when number_of_years <= 0. The function computes annual-percentage-rate interest by delegating to compound_interest with number_of_years * 365 periods, so a non-positive year count is meaningless and rejected before any math runs. It is a deliberate input-contract check, not a numerical failure.","triggerScenarios":"Calling apr_interest(principal, rate, years) with years = 0 or a negative value, e.g. apr_interest(10000.0, 0.01, 0) or apr_interest(10000.0, 0.01, -3). Note years is checked first, so a bad years value masks bad rate/principal.","commonSituations":"Passing a computed duration that can be 0 (e.g. (end_year - start_year) before validation), unit confusion (months passed where years expected, giving fractional-but-positive values that silently work), or defaults of 0 in a config dict.","solutions":["Pass a strictly positive number of years: at minimum 1 (or a positive fraction for partial years).","If the value is user-supplied or computed, validate it at the call site before invoking apr_interest.","If 0 years is legitimately possible in your flow, short-circuit it: return the principal unchanged instead of calling the function."],"exampleFix":"# before\napr_interest(10000.0, 0.05, end_year - start_year)  # ValueError when equal\n\n# after\nyears = end_year - start_year\nvalue = 10000.0 if years <= 0 else apr_interest(10000.0, 0.05, years)","handlingStrategy":"validation","validationCode":"years = end_year - start_year\nif years <= 0:\n    raise ValueError(f\"term must be positive, got {years}\")\napr_interest(10000.0, 0.05, years)","typeGuard":null,"tryCatchPattern":"try:\n    value = apr_interest(p, r, y)\nexcept ValueError as exc:\n    if 'number_of_years' in str(exc):\n        raise ValueError(f'invalid term: {y}') from exc\n    raise","preventionTips":["Validate durations at the boundary where they are computed, not inside loops of financial calls.","Remember the check order: years, then rate, then principal — fix the first bad argument first."],"tags":["finance","input-validation","valueerror"],"backgroundTag":null,"analyzedSha":"f5988cc09713315817df6a7e327e258013a94440","analyzedAt":"2026-08-14T17:30:07.041Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}