sansan0/TrendRadar · error · InvalidParameterError

开始日期不能晚于结束日期

Error message

开始日期不能晚于结束日期

What it means

Raised by normalize_date_range when both dates parse successfully but start_date > end_date — an inverted range. The suggestion echoes the offending pair. Note equality is allowed (single-day range), only strictly-later starts are rejected.

Source

Thrown at mcp_server/utils/validators.py:447

        raise InvalidParameterError(
            "date_range 必须是字典类型、日期字符串或有效的JSON字符串",
            suggestion='例如: {"start": "2025-10-01", "end": "2025-10-11"} 或 "2025-10-01"'
        )

    start_str = date_range.get("start")
    end_str = date_range.get("end")

    if not start_str or not end_str:
        raise InvalidParameterError(
            "date_range 必须包含 start 和 end 字段",
            suggestion='例如: {"start": "2025-10-01", "end": "2025-10-11"}'
        )

    start_date = validate_date(start_str)
    end_date = validate_date(end_str)

    if start_date > end_date:
        raise InvalidParameterError(
            "开始日期不能晚于结束日期",
            suggestion=f"start: {start_str}, end: {end_str}"
        )

    # 检查日期是否在未来
    today = datetime.now().date()
    if start_date.date() > today or end_date.date() > today:
        # 获取可用日期范围提示
        try:
            from ..services.data_service import DataService
            data_service = DataService()
            earliest, latest = data_service.get_available_date_range()

            if earliest and latest:
                available_range = f"{earliest.strftime('%Y-%m-%d')} 至 {latest.strftime('%Y-%m-%d')}"
            else:
                available_range = "无可用数据"
        except Exception:

View on GitHub (pinned to 8ee26026ba)

Solutions

  1. Swap the values so start <= end
  2. Compute end first, then start = end - timedelta(days=N), never the reverse unguarded
  3. Add a client-side assert: if (start > end) [start, end] = [end, start]
  4. Remember single-day queries can use start == end or the bare date string

Example fix

# before
{"date_range": {"start": "2025-10-11", "end": "2025-10-01"}}
# after
{"date_range": {"start": "2025-10-01", "end": "2025-10-11"}}

# defensive swap
start, end = min(start, end), max(start, end)
Defensive patterns

Strategy: validation

Validate before calling

let [start, end] = [dr.start, dr.end];
if (new Date(start) > new Date(end)) [start, end] = [end, start]; // or reject in UI

Type guard

const isOrderedRange = (s: string, e: string): boolean => s <= e; // ISO strings compare lexicographically

Try / catch

try { call({ date_range: dr }); }
catch (e) {
  if (/开始日期不能晚于结束日期/.test(e.message)) call({ date_range: { start: dr.end, end: dr.start } });
  else throw e;
}

Prevention

When it happens

Trigger: Sending {"start": "2025-10-11", "end": "2025-10-01"}; swapping the keys; auto-generated ranges where the bound computation inverted (e.g. subtracting from the wrong end); timezone-crossing logic that produces off-by-one inversions near midnight.

Common situations: UI date pickers returning fields in display order (mm-dd) mapped to start/end wrongly; LLMs writing later date first; code computing start = today, end = today - N days by accident.

Related errors


AI-assisted analysis of sansan0/TrendRadar@8ee26026ba (2026-08-15). Data as JSON: /api/errors/ca1b98ab89589bc8. Report an issue: GitHub.