TheAlgorithms/Python · error · ValueError
Useful years cannot be less than 1
Error message
Useful years cannot be less than 1
What it means
Raised by straight_line_depreciation() when useful_years is an int but < 1. range(useful_years) would produce no periods, so a zero or negative asset life is rejected. This check runs after the isinstance check, so the value is guaranteed integral when it fires.
Source
Thrown at financial/straight_line_depreciation.py:59
:param residual_value: Residual value of the asset at the end of its useful life
:return: A list of annual depreciation expenses over the asset's useful life
>>> straight_line_depreciation(10, 1100.0, 100.0)
[100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0]
>>> straight_line_depreciation(6, 1250.0, 50.0)
[200.0, 200.0, 200.0, 200.0, 200.0, 200.0]
>>> straight_line_depreciation(4, 1001.0)
[250.25, 250.25, 250.25, 250.25]
>>> straight_line_depreciation(11, 380.0, 50.0)
[30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0]
>>> straight_line_depreciation(1, 4985, 100)
[4885.0]
"""
if not isinstance(useful_years, int):
raise TypeError("Useful years must be an integer")
if useful_years < 1:
raise ValueError("Useful years cannot be less than 1")
if not isinstance(purchase_value, (float, int)):
raise TypeError("Purchase value must be numeric")
if not isinstance(residual_value, (float, int)):
raise TypeError("Residual value must be numeric")
if purchase_value < 0.0:
raise ValueError("Purchase value cannot be less than zero")
if purchase_value < residual_value:
raise ValueError("Purchase value cannot be less than residual value")
# Calculate annual depreciation expense
depreciable_cost = purchase_value - residual_value
annual_depreciation_expense = depreciable_cost / useful_years
# List of annual depreciation expensesView on GitHub (pinned to f5988cc097)
Solutions
- Pass useful_years >= 1; the minimum meaningful schedule is one full-year period.
- Guard computed lifespans and treat 0 as missing data rather than clamping silently.
- Reject zero-life assets upstream — they usually indicate missing acquisition data.
Example fix
# before
life = retire_year - acquire_year # 0 for same-year assets
straight_line_depreciation(life, 1250.0, 50.0)
# after
life = retire_year - acquire_year
if life < 1:
raise ValueError(f'asset life must be >= 1 year, got {life}')
straight_line_depreciation(life, 1250.0, 50.0) Defensive patterns
Strategy: validation
Validate before calling
if not isinstance(useful_years, int) or useful_years < 1:
raise ValueError('useful_years must be an int >= 1')
straight_line_depreciation(useful_years, purchase, residual) Try / catch
try:
sched = straight_line_depreciation(y, p, r)
except ValueError as exc:
if 'less than 1' in str(exc):
raise ValueError(f'invalid asset life: {y}') from exc
raise Prevention
- Treat a 0-year life as a data-quality alarm, not a clamp-to-1 case.
- This raises ValueError while type problems raise TypeError — order your except clauses accordingly.
When it happens
Trigger: Calling straight_line_depreciation(0, 1250.0, 50.0) or with a negative int such as -3.
Common situations: Lifespans computed as (retire_year - acquire_year) that hit 0 for same-year assets, config placeholders of 0 meaning 'not set', or sign errors from data entry.
Related errors
- number_of_years must be > 0
- nominal_annual_percentage_rate must be >= 0
- Discount rate cannot be negative
- Cash flows list cannot be empty
- Window size must be a positive integer
AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14).
Data as JSON: /api/errors/b56e9dddb0dd1ed3.
Report an issue: GitHub.