TheAlgorithms/Python · error · TypeError
Residual value must be numeric
Error message
Residual value must be numeric
What it means
Raised by straight_line_depreciation() when residual_value is not int or float (TypeError). residual_value participates in subtraction (purchase - residual), so non-numeric inputs fail fast before the depreciation schedule is built. It is the fourth check, after useful_years type/range and purchase_value type.
Source
Thrown at financial/straight_line_depreciation.py:65
>>> 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 expenses
list_of_depreciation_expenses = []
accumulated_depreciation_expense = 0.0
for period in range(useful_years):
if period != useful_years - 1:
accumulated_depreciation_expense += annual_depreciation_expense
list_of_depreciation_expenses.append(annual_depreciation_expense)View on GitHub (pinned to f5988cc097)
Solutions
- Pass residual as a number; use 0 when there is no salvage value.
- Convert None -> 0.0 at the boundary if 'unspecified' means 'no residual' in your domain.
- Apply the same numeric parsing you use for purchase_value — the checks are symmetric.
Example fix
# before
straight_line_depreciation(5, 1250.0, asset.get('residual')) # None when absent
# after
straight_line_depreciation(5, 1250.0, asset.get('residual') or 0.0) Defensive patterns
Strategy: type-guard
Validate before calling
residual = residual if isinstance(residual, (int, float)) else 0.0 straight_line_depreciation(5, 1250.0, residual)
Type guard
def is_numeric(v: object) -> bool:
return isinstance(v, (int, float)) and not isinstance(v, bool) Try / catch
try:
sched = straight_line_depreciation(y, p, r)
except TypeError as exc:
if 'Residual value' in str(exc):
sched = straight_line_depreciation(y, p, 0.0)
else:
raise Prevention
- Normalize None salvage values to 0.0 where the domain allows it.
- Keep purchase and residual types consistent — both must be plain int/float.
When it happens
Trigger: Calling straight_line_depreciation(5, 1250.0, '50.0'), passing None (common for 'no salvage value' defaults), or a Decimal salvage figure.
Common situations: Optional salvage-value fields defaulting to None in forms and APIs, string inputs from config files, or mixed types when purchase is float but residual comes from a different source.
Related errors
- Useful years must be an integer
- Purchase value must be numeric
- Input value of [number={number}] must be an integer
- Input value of [number={number}] must be an integer
- Input value of [number={number}] must be an integer
AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14).
Data as JSON: /api/errors/082decb2b6f84aa1.
Report an issue: GitHub.