sansan0/TrendRadar · error · InvalidParameterError

日期解析失败: {stripped}

Error message

日期解析失败: {stripped}

What it means

Raised by normalize_date_range's catch-all: the natural-language branch threw an unexpected (non-InvalidParameterError) exception. Looking at the code, after a successful parse it does datetime.strptime(dr['start'], '%Y-%m-%d') — so if DateParser ever returned success with a malformed date string, or any internal bug (KeyError on 'date_range', TypeError, etc.) fired, it is masked as '日期解析失败'.

Source

Thrown at mcp_server/utils/validators.py:423

                )
        # 3. 尝试自然语言解析
        else:
            try:
                result = DateParser.resolve_date_range_expression(stripped)
                if result.get("success"):
                    dr = result["date_range"]
                    start_date = datetime.strptime(dr["start"], "%Y-%m-%d")
                    end_date = datetime.strptime(dr["end"], "%Y-%m-%d")
                    return (start_date, end_date)
                else:
                    raise InvalidParameterError(
                        f"无法识别的日期表达式: {stripped}",
                        suggestion="支持格式: YYYY-MM-DD, {\"start\": \"...\", \"end\": \"...\"}, 或自然语言(今天、本周、最近7天等)"
                    )
            except InvalidParameterError:
                raise
            except Exception:
                raise InvalidParameterError(
                    f"日期解析失败: {stripped}",
                    suggestion="支持格式: YYYY-MM-DD, {\"start\": \"...\", \"end\": \"...\"}, 或自然语言(今天、本周、最近7天等)"
                )

    if not isinstance(date_range, dict):
        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"}'
        )

View on GitHub (pinned to 8ee26026ba)

Solutions

  1. As a caller: retry with explicit ISO dates {"start": "...", "end": "..."} to bypass the natural-language path entirely
  2. If you own the code: log the original exception (currently swallowed by 'except Exception') to identify the real failure
  3. Audit DateParser._calculate_date_range return values so start/end are always zero-padded YYYY-MM-DD strings
  4. Add a regression test per supported expression asserting strptime succeeds on the output

Example fix

# before
except Exception:
    raise InvalidParameterError(f"日期解析失败: {stripped}", ...)
# after
except Exception as e:
    logger.exception("date expression internal failure")
    raise InvalidParameterError(f"日期解析失败: {stripped} (原因: {e})", ...)
Defensive patterns

Strategy: fallback

Validate before calling

// Avoid the natural-language path entirely: always send structured ranges
date_range = { start: isoDaysAgo(7), end: isoToday() };

Try / catch

try { call({ date_range: expr }); }
catch (e) {
  if (/日期解析失败/.test(e.message)) {
    // internal path failed; fall back to explicit ISO range
    call({ date_range: { start: isoDaysAgo(7), end: isoToday() } });
  } else throw e;
}

Prevention

When it happens

Trigger: A DateParser success result whose date_range.start/end are not strict YYYY-MM-DD (e.g. a pattern returns a datetime or different format), or an exception inside resolve_date_range_expression itself (bad regex input type, None field). Essentially: an internal inconsistency rather than a user formatting mistake.

Common situations: Server-side bugs after adding a new date expression to DateParser without normalizing output to ISO strings; timezone/locale side effects; None leaking into the result dict. Users cannot fix this by reformatting — the generic message hides the real traceback.

Related errors


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