{"record":{"id":"c7ef2eb970beca1e","repo":"sansan0/TrendRadar","slug":"day-plan-plan-key-period-period-key","errorCode":null,"errorMessage":"day_plan[{plan_key}] 引用了不存在的 period: {period_key}","messagePattern":"day_plan\\[(.+?)\\] 引用了不存在的 period: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"trendradar/core/scheduler.py","lineNumber":341,"sourceCode":"                raise ValueError(f\"timeline 缺少必须字段: {key}\")\n\n        # week_map 必须覆盖 1..7\n        for day in range(1, 8):\n            if day not in timeline[\"week_map\"]:\n                raise ValueError(f\"week_map 缺少星期映射: {day}\")\n\n        # day_plan 引用完整性\n        for day, plan_key in timeline[\"week_map\"].items():\n            if plan_key not in timeline[\"day_plans\"]:\n                raise ValueError(\n                    f\"week_map[{day}] 引用了不存在的 day_plan: {plan_key}\"\n                )\n\n        # period 引用完整性\n        for plan_key, plan in timeline[\"day_plans\"].items():\n            for period_key in plan.get(\"periods\", []):\n                if period_key not in timeline[\"periods\"]:\n                    raise ValueError(\n                        f\"day_plan[{plan_key}] 引用了不存在的 period: {period_key}\"\n                    )\n\n        # 时间格式校验\n        for period_key, period in timeline[\"periods\"].items():\n            if \"start\" not in period or \"end\" not in period:\n                raise ValueError(\n                    f\"period '{period_key}' 缺少 start 或 end 字段\"\n                )\n            self._validate_hhmm(period[\"start\"], f\"{period_key}.start\")\n            self._validate_hhmm(period[\"end\"], f\"{period_key}.end\")\n            if period[\"start\"] == period[\"end\"]:\n                raise ValueError(\n                    f\"period '{period_key}' 的 start 与 end 不能相同: {period['start']}\"\n                )\n\n        # 检查冲突策略下的重叠\n        policy = timeline.get(\"overlap\", {}).get(\"policy\", \"error_on_overlap\")","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/sansan0/TrendRadar/blob/8ee26026ba6c11dec41a95fb3895a7162876caa1/trendradar/core/scheduler.py#L323-L359","documentation":"Raised by _validate_timeline when a period referenced from a day_plan lacks a 'start' or 'end' field. Every entry under timeline.periods must define both boundaries in HH:MM; the check runs after referential integrity, so the period key exists but is malformed.","triggerScenarios":"Defining periods: {night: {start: \"22:00\"}} without end; naming the fields differently ('from'/'to' instead of 'start'/'end'); a period set to null in YAML.","commonSituations":"Translating a schedule from another tool whose field names differ; YAML where a value line was accidentally deleted; copying an example and not replacing placeholder keys.","solutions":["Add both start and end (HH:MM strings) to the period named in the message.","Use the exact field names 'start' and 'end'.","For cross-midnight spans, end may be earlier than start (supported) but must still be present."],"exampleFix":"# before\nperiods:\n  night: {start: \"22:00\"}\n# after\nperiods:\n  night: {start: \"22:00\", end: \"06:00\"}","handlingStrategy":"validation","validationCode":"import re\nHHMM = re.compile(r\"^([01]\\d|2[0-3]):[0-5]\\d$\")\nfor key, p in timeline.get(\"periods\", {}).items():\n    if \"start\" not in p or \"end\" not in p:\n        raise ValueError(f\"period '{key}' missing start/end\")\n    assert HHMM.match(p[\"start\"]) and HHMM.match(p[\"end\"]), f\"period '{key}' bad HH:MM\"","typeGuard":"def is_wellformed_period(p: dict) -> bool:\n    return (\n        isinstance(p, dict)\n        and isinstance(p.get(\"start\"), str)\n        and isinstance(p.get(\"end\"), str)\n    )","tryCatchPattern":"try:\n    scheduler = Scheduler(schedule_config, timeline_data)\nexcept ValueError as e:\n    if \"缺少 start 或 end\" in str(e):\n        raise SystemExit(f\"timeline period incomplete: {e}\")\n    raise","preventionTips":["Use exactly 'start' and 'end' field names with HH:MM string values.","Lint all periods for both fields before starting the scheduler."],"tags":["scheduler","config","missing-field","validation"],"backgroundTag":null,"analyzedSha":"8ee26026ba6c11dec41a95fb3895a7162876caa1","analyzedAt":"2026-08-15T01:42:18.084Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}