{"record":{"id":"493c39dd2c72724e","repo":"sansan0/TrendRadar","slug":"week-map-day","errorCode":null,"errorMessage":"week_map 缺少星期映射: {day}","messagePattern":"week_map 缺少星期映射: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"trendradar/core/scheduler.py","lineNumber":328,"sourceCode":"    # 校验\n    # ========================================\n\n    def _validate_timeline(self, timeline: Dict[str, Any]) -> None:\n        \"\"\"\n        启动时校验 timeline 配置\n\n        Raises:\n            ValueError: 配置不合法时抛出\n        \"\"\"\n        required_top_keys = [\"default\", \"periods\", \"day_plans\", \"week_map\"]\n        for key in required_top_keys:\n            if key not in timeline:\n                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():","sourceCodeStart":310,"sourceCodeEnd":346,"githubUrl":"https://github.com/sansan0/TrendRadar/blob/8ee26026ba6c11dec41a95fb3895a7162876caa1/trendradar/core/scheduler.py#L310-L346","documentation":"Raised by _validate_timeline when week_map does not cover all ISO weekdays 1..7. Every day must be mapped to some day_plan, even if that plan is empty — the scheduler resolves 'today' unconditionally on each tick. This is the startup-time twin of the runtime error at scheduler.py:131.","triggerScenarios":"A week_map with only keys 1-5 (weekdays only); numeric keys quoted as strings ('6' instead of 6) so the integer loop misses them; a weekend day deleted intentionally.","commonSituations":"Users modeling 'no runs on weekends' by omitting the days; YAML quoting turning integer keys into strings; partial copy from an example that only showed weekdays.","solutions":["Add entries for days 6 and 7 (and any other missing day) pointing at a rest/empty day_plan.","Ensure weekday keys are integers 1-7, not strings, in YAML.","Remember the contract: absence of a key is invalid; an empty periods list is the correct way to express 'nothing scheduled'."],"exampleFix":"# before\nweek_map: {1: work, 2: work, 3: work, 4: work, 5: work}\n# after\nweek_map: {1: work, 2: work, 3: work, 4: work, 5: work, 6: rest, 7: rest}\nday_plans: {work: {periods: [...]}, rest: {periods: []}}","handlingStrategy":"validation","validationCode":"week_map = timeline.get(\"week_map\", {})\nmissing_days = [d for d in range(1, 8) if d not in week_map]\nif missing_days:\n    raise ValueError(f\"week_map incomplete, missing days: {missing_days}\")\n# keys must be ints, not strings\nassert all(isinstance(d, int) for d in week_map), \"weekday keys must be ints 1-7\"","typeGuard":"def week_map_covers_all_days(t: dict) -> bool:\n    wm = t.get(\"week_map\", {})\n    return all(d in wm for d in range(1, 8))","tryCatchPattern":"try:\n    scheduler = Scheduler(schedule_config, timeline_data)\nexcept ValueError as e:\n    if \"week_map 缺少星期映射\" in str(e):\n        raise SystemExit(f\"map days {range(1,8)} to day_plans (use a rest plan for off-days)\")\n    raise","preventionTips":["Always define all 7 weekday keys; use empty day_plans for off-days.","Keep weekday keys as integers in YAML (no quotes)."],"tags":["scheduler","config","week-map","validation"],"backgroundTag":null,"analyzedSha":"8ee26026ba6c11dec41a95fb3895a7162876caa1","analyzedAt":"2026-08-15T01:42:18.084Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}