Skip to content

fix: handle month overflow in duration_in_seconds for multi-month durations - #23099

Merged
1 commit merged into
BerriAI:litellm_oss_staging_03_09_2026from
jnMetaCode:fix/duration-parser-month-overflow
Mar 10, 2026
Merged

fix: handle month overflow in duration_in_seconds for multi-month durations#23099
1 commit merged into
BerriAI:litellm_oss_staging_03_09_2026from
jnMetaCode:fix/duration-parser-month-overflow

Conversation

@jnMetaCode

Copy link
Copy Markdown
Contributor

Summary

duration_in_seconds("Nmo") crashes with ValueError: month must be in 1..12 when current_month + N > 12 and current_month != 12.

The existing code only handles the year rollover for current_month == 12, but not for cases like November + 2 months = month 13. This affects any multi-month budget duration (e.g., "2mo", "3mo") used in Router provider budget routing or Proxy key/team generation.

Before: month=11, value=2target_month=13ValueError
After: Uses modular arithmetic: target_month = (total_months % 12) + 1, target_year += total_months // 12

Test plan

  • Verify duration_in_seconds("2mo") works correctly in November (month 11)
  • Verify duration_in_seconds("3mo") works correctly in October (month 10)
  • Verify single-month duration_in_seconds("1mo") behavior is unchanged
  • Verify December rollover still works correctly

…ations

When value > 1 (e.g., "2mo") and current_month + value > 12,
target_month exceeds valid range (1-12), causing ValueError in
datetime constructor. For example, calling duration_in_seconds("2mo")
in November produces target_month=13.

Use modular arithmetic to correctly wrap months and increment year.

Signed-off-by: JiangNan <1394485448@qq.com>
@vercel

vercel Bot commented Mar 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Error Error Mar 8, 2026 9:36am

Request Review

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@greptile-apps

greptile-apps Bot commented Mar 8, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a ValueError: month must be in 1..12 crash in duration_in_seconds for multi-month duration strings (e.g., "2mo", "3mo") by replacing a December-only special case with generalized modular arithmetic. The single changed file is litellm/litellm_core_utils/duration_parser.py.

Key observations:

  • Fix is mathematically correct. The new formula total_months = current_time.month - 1 + value converts to a 0-indexed month offset, then target_year = current_time.year + total_months // 12 and target_month = total_months % 12 + 1 correctly handles all overflow cases including multi-year spans.

  • Secondary bug also fixed. The old code's December branch unconditionally set target_month = 1 regardless of value, meaning "2mo" in December would have incorrectly resolved to January (off by one month). The new code returns the correct February.

  • No test coverage added for multi-month cases. The PR description includes a test plan but no actual test code was added. The existing tests only cover the single-month case ("1mo"); there are currently zero tests directly verifying duration_in_seconds("2mo"), duration_in_seconds("3mo"), etc.—exactly the scenarios this fix addresses.

Confidence Score: 4/5

  • Safe to merge; the fix is logically correct and backward-compatible, but lacks test coverage for the newly-fixed multi-month code paths.
  • The arithmetic change is correct across all verified edge cases (any month + any N months, including multi-year spans and the previously-broken December + N > 1 case). The change is confined to a single utility function with no API surface changes, and the surrounding logic (get_last_day_of_month, clamping of target_day) is unaffected. Score is 4 rather than 5 because there are no new unit tests to document or protect the fixed behavior for multi-month durations, despite a test plan being outlined in the PR description.
  • litellm/litellm_core_utils/duration_parser.py — Missing unit tests for the newly-fixed multi-month duration cases ("2mo", "3mo", etc.)

Last reviewed commit: 947db46

Comment on lines +67 to +70
# Calculate target month and year, handling overflow past December
total_months = current_time.month - 1 + value # 0-indexed months
target_year = current_time.year + total_months // 12
target_month = total_months % 12 + 1 # back to 1-indexed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description outlines a test plan (November + 2 months, October + 3 months, etc.) but no test code was actually added. The existing test file only exercises get_next_standardized_reset_time; there are currently zero tests directly covering duration_in_seconds("Nmo") for multi-month cases like "2mo" or "3mo" — the scenarios that this fix addresses.

Please add unit tests for the fixed code paths as described in the test plan, for example:

from unittest.mock import patch
from datetime import datetime
from litellm.litellm_core_utils.duration_parser import duration_in_seconds

def _mock_time(year, month, day):
    dt = datetime(year, month, day, 12, 0, 0)
    return dt.timestamp()

def test_november_plus_two_months():
    with patch("time.time", return_value=_mock_time(2023, 11, 15)):
        result = duration_in_seconds("2mo")
        assert result > 0

def test_october_plus_three_months():
    with patch("time.time", return_value=_mock_time(2023, 10, 15)):
        result = duration_in_seconds("3mo")
        assert result > 0

def test_december_plus_one_month():
    with patch("time.time", return_value=_mock_time(2023, 12, 15)):
        result = duration_in_seconds("1mo")
        assert result > 0

Rule Used: What: Ensure that any PR claiming to fix an issue ... (source)

@jnMetaCode

Copy link
Copy Markdown
Contributor Author

I have read the CLA Document and I hereby sign the CLA

1 similar comment
@jnMetaCode

Copy link
Copy Markdown
Contributor Author

I have read the CLA Document and I hereby sign the CLA

@ghost
ghost changed the base branch from main to litellm_oss_staging_03_09_2026 March 10, 2026 02:46
@ghost
ghost merged commit 0d3735f into BerriAI:litellm_oss_staging_03_09_2026 Mar 10, 2026
30 of 38 checks passed
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
…ations (BerriAI#23099)

When value > 1 (e.g., "2mo") and current_month + value > 12,
target_month exceeds valid range (1-12), causing ValueError in
datetime constructor. For example, calling duration_in_seconds("2mo")
in November produces target_month=13.

Use modular arithmetic to correctly wrap months and increment year.

Signed-off-by: JiangNan <1394485448@qq.com>
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants