sansan0/TrendRadar · error · ValueError
period '{period_key}' 的 start 与 end 不能相同: {period['start']}
Error message
period '{period_key}' 的 start 与 end 不能相同: {period['start']} What it means
Raised by _check_period_overlaps during startup validation when two periods within the same day_plan have overlapping time ranges and overlap.policy is 'error_on_overlap' (default). This is the eager, whole-timeline version of the runtime conflict error at scheduler.py:220: every day plan's periods are pairwise-checked (cross-midnight ranges supported via minute conversion) before the scheduler ever runs.
Source
Thrown at trendradar/core/scheduler.py:354
# period 引用完整性
for plan_key, plan in timeline["day_plans"].items():
for period_key in plan.get("periods", []):
if period_key not in timeline["periods"]:
raise ValueError(
f"day_plan[{plan_key}] 引用了不存在的 period: {period_key}"
)
# 时间格式校验
for period_key, period in timeline["periods"].items():
if "start" not in period or "end" not in period:
raise ValueError(
f"period '{period_key}' 缺少 start 或 end 字段"
)
self._validate_hhmm(period["start"], f"{period_key}.start")
self._validate_hhmm(period["end"], f"{period_key}.end")
if period["start"] == period["end"]:
raise ValueError(
f"period '{period_key}' 的 start 与 end 不能相同: {period['start']}"
)
# 检查冲突策略下的重叠
policy = timeline.get("overlap", {}).get("policy", "error_on_overlap")
if policy == "error_on_overlap":
self._check_period_overlaps(timeline)
def _check_period_overlaps(self, timeline: Dict[str, Any]) -> None:
"""
检查每个日计划中的时间段是否存在重叠
仅在 overlap.policy == "error_on_overlap" 时调用
"""
periods = timeline.get("periods", {})
for plan_key, plan in timeline["day_plans"].items():
period_keys = plan.get("periods", [])View on GitHub (pinned to 8ee26026ba)
Solutions
- Make the listed ranges disjoint (adjust start/end so no pair overlaps).
- If overlap is intended with the later period winning, set overlap: {policy: last_wins} — validation is then skipped and the runtime path logs warnings instead.
- Audit every day_plan, not just one: the check iterates all plans and all period pairs.
Example fix
# before (policy default)
day_plans:
work: {periods: [morning, noon]}
periods:
morning: {start: "08:00", end: "12:00"}
noon: {start: "11:30", end: "13:30"}
# after
periods:
morning: {start: "08:00", end: "11:30"}
noon: {start: "11:30", end: "13:30"}
# or add: overlap: {policy: last_wins} Defensive patterns
Strategy: validation
Validate before calling
def to_min(t): return int(t[:2]) * 60 + int(t[3:])
def overlaps(s1, e1, s2, e2):
a1, b1, a2, b2 = to_min(s1), to_min(e1), to_min(s2), to_min(e2)
if a1 == b1 or a2 == b2:
return False
spans = []
for a, b in ((a1, b1), (a2, b2)):
if a < b:
spans.append((a, b))
else: # cross-midnight
spans.append((a, 24 * 60))
spans.append((0, b))
# naive pairwise check on split intervals is enough for a lint
flat = sorted(spans)
for i in range(1, len(flat)):
if flat[i][0] < flat[i - 1][1]:
return True
return False
policy = timeline.get("overlap", {}).get("policy", "error_on_overlap")
if policy == "error_on_overlap":
for plan_key, plan in timeline["day_plans"].items():
keys = plan.get("periods", [])
for i in range(len(keys)):
for j in range(i + 1, len(keys)):
pi, pj = timeline["periods"][keys[i]], timeline["periods"][keys[j]]
if overlaps(pi["start"], pi["end"], pj["start"], pj["end"]):
raise ValueError(f"{plan_key}: {keys[i]} overlaps {keys[j]}") Try / catch
try:
scheduler = Scheduler(schedule_config, timeline_data)
except ValueError as e:
if "存在重叠" in str(e):
raise SystemExit(f"timeline has overlapping periods: {e}")
raise Prevention
- Run an overlap lint on every timeline edit (or in CI).
- Declare overlap.policy: last_wins explicitly when overlap is intended.
When it happens
Trigger: A day_plan listing morning 08:00-12:00 and noon 11:30-13:30; overlap.policy unset or 'error_on_overlap'. Triggered at validation time regardless of current clock, unlike the runtime variant.
Common situations: Same as the runtime overlap case: hand-edited boundaries, periods copied between plans, cross-midnight spans overlapping morning periods (e.g. 22:00-02:00 vs 01:00-03:00).
Related errors
- 不支持的传输模式: {transport}
- DATA_NOT_FOUND
- 未知的预设模板: '{preset}',可选值: {', '.join(presets.keys())}, custom
- 检测到时间段重叠冲突: {', '.join(conflicting)} 在 {now_hhmm} 重叠。请调整时间段配
- timeline 缺少必须字段: {key}
AI-assisted analysis of sansan0/TrendRadar@8ee26026ba (2026-08-15).
Data as JSON: /api/errors/71e6ffc2cc3e3477.
Report an issue: GitHub.