sansan0/TrendRadar · error · ValueError

day_plan '{plan_key}' 中时间段 '{ranges[i][0]}' ({ranges[i][1]}-

Error message

day_plan '{plan_key}' 中时间段 '{ranges[i][0]}' ({ranges[i][1]}-{ranges[i][2]}) 与 '{ranges[j][0]}' ({ranges[j][1]}-{ranges[j][2]}) 存在重叠。请调整时间段,或将 overlap.policy 设为 'last_wins'

What it means

Duplicate coverage of scheduler.py:390's message — same raise site, same meaning as error 78's underlying check but reached via the runtime path: _find_active_period found multiple candidate periods containing the current HH:MM and overlap.policy is 'error_on_overlap'. The scheduler lists the conflicting period names and times and tells the user how to opt into 'last_wins'.

Source

Thrown at trendradar/core/scheduler.py:390

            period_keys = plan.get("periods", [])
            if len(period_keys) <= 1:
                continue

            # 收集每个时间段的范围
            ranges = []
            for pk in period_keys:
                p = periods.get(pk, {})
                if "start" in p and "end" in p:
                    ranges.append((pk, p["start"], p["end"]))

            # 两两检查重叠
            for i in range(len(ranges)):
                for j in range(i + 1, len(ranges)):
                    if self._ranges_overlap(
                        ranges[i][1], ranges[i][2],
                        ranges[j][1], ranges[j][2],
                    ):
                        raise ValueError(
                            f"day_plan '{plan_key}' 中时间段 '{ranges[i][0]}' "
                            f"({ranges[i][1]}-{ranges[i][2]}) 与 '{ranges[j][0]}' "
                            f"({ranges[j][1]}-{ranges[j][2]}) 存在重叠。"
                            f"请调整时间段,或将 overlap.policy 设为 'last_wins'"
                        )

    @staticmethod
    def _ranges_overlap(s1: str, e1: str, s2: str, e2: str) -> bool:
        """检查两个时间范围是否重叠(支持跨日)"""
        def to_minutes(t: str) -> int:
            h, m = t.split(":")
            return int(h) * 60 + int(m)

        def expand_range(start: str, end: str) -> List[tuple]:
            """将时间范围展开为分钟段列表,跨日时拆分为两段"""
            s = to_minutes(start)
            e = to_minutes(end)
            if s <= e:

View on GitHub (pinned to 8ee26026ba)

Solutions

  1. Fix the period boundaries so they do not overlap.
  2. Set overlap: {policy: last_wins} to let the last-listed period win (warning logged, no error).
  3. If building timelines programmatically, run _validate_timeline before entering the scheduling loop.

Example fix

# before
periods:
  a: {start: "08:00", end: "12:00"}
  b: {start: "11:00", end: "13:00"}
# after
periods:
  a: {start: "08:00", end: "11:00"}
  b: {start: "11:00", end: "13:00"}
# or: overlap: {policy: last_wins}
Defensive patterns

Strategy: validation

Validate before calling

# reuse the pairwise overlap lint from startup validation before resolve()
for plan in timeline["day_plans"].values():
    keys = plan.get("periods", [])
    for i in range(len(keys)):
        for j in range(i + 1, len(keys)):
            if ranges_overlap(timeline["periods"][keys[i]], timeline["periods"][keys[j]]):
                raise ValueError(f"periods {keys[i]}/{keys[j]} overlap")
cfg = scheduler.resolve()

Try / catch

try:
    cfg = scheduler.resolve()
except ValueError as e:
    if "时间段重叠冲突" in str(e):
        # deterministic config bug: fix periods or set overlap.policy=last_wins
        raise SystemExit(f"schedule config error: {e}")
    raise

Prevention

When it happens

Trigger: resolve() called at a time of day inside two periods of the active day plan (e.g. 11:30 with 08:00-12:00 and 11:00-13:00 both active); default policy. Note the startup validator (_check_period_overlaps) normally catches this earlier, so reaching the runtime raise means validation was skipped or the timeline mutated afterwards.

Common situations: Dynamically built or patched timelines that bypass _validate_timeline; periods added at runtime by orchestration code; cross-midnight spans overlapping early-morning periods.

Related errors


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