{"record":{"id":"6068b0ba88602d44","repo":"jdx/mise","slug":"expected-first-calendar-interval-dictionary-got","errorCode":null,"errorMessage":"expected first calendar interval dictionary, got {value:?}","messagePattern":"expected first calendar interval dictionary, got (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/launchd.rs","lineNumber":868,"sourceCode":"            working_directory: None,\n            stdout_path: None,\n            stderr_path: None,\n            kickstart: false,\n        };\n        let plist = render_plist(&request).unwrap();\n        let dict = match Value::from_reader_xml(Cursor::new(plist.as_slice())).unwrap() {\n            Value::Dictionary(dict) => dict,\n            value => panic!(\"expected dictionary, got {value:?}\"),\n        };\n        match dict.get(\"StartCalendarInterval\") {\n            Some(Value::Array(intervals)) => {\n                assert_eq!(intervals.len(), 2);\n                match &intervals[0] {\n                    Value::Dictionary(interval) => {\n                        assert_eq!(interval.get(\"Hour\"), Some(&Value::Integer(3.into())));\n                        assert_eq!(interval.get(\"Minute\"), Some(&Value::Integer(0.into())));\n                    }\n                    value => panic!(\"expected first calendar interval dictionary, got {value:?}\"),\n                }\n                match &intervals[1] {\n                    Value::Dictionary(interval) => {\n                        assert_eq!(interval.get(\"Hour\"), Some(&Value::Integer(12.into())));\n                        assert_eq!(interval.get(\"Weekday\"), Some(&Value::Integer(1.into())));\n                    }\n                    value => panic!(\"expected second calendar interval dictionary, got {value:?}\"),\n                }\n            }\n            value => panic!(\"expected StartCalendarInterval array, got {value:?}\"),\n        }\n        assert_eq!(dict.get(\"ThrottleInterval\"), None);\n        assert_eq!(dict.get(\"QueueDirectories\"), None);\n    }\n\n    #[test]\n    fn test_render_plist_throttle_and_queue_directories() {\n        let request = LaunchdRequest::from_toml(","sourceCodeStart":850,"sourceCodeEnd":886,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/launchd.rs#L850-L886","documentation":"Test assertion panic in test_render_plist_multiple_calendar_intervals. The test asserts the first StartCalendarInterval entry is a dictionary with Hour=3 and Minute=0; if intervals[0] is not a dictionary, this panic fires with the actual value.","triggerScenarios":"render_plist emits multiple calendar intervals where the first element of the StartCalendarInterval array is a non-dictionary value (wrong ordering, flattened value, or wrong element type).","commonSituations":"Reordering interval emission, serializing intervals as arrays of scalars, or a change that puts the weekday-based interval first.","solutions":["Inspect intervals[0] via the {value:?} panic payload","Verify render_plist preserves request calendar-interval ordering and emits each interval as a dictionary with Hour/Minute/Weekday keys","Fix the serializer or reorder the test data so the daily 3:00 interval is first"],"exampleFix":"// before\nvalue => panic!(\"expected first calendar interval dictionary, got {value:?}\"),\n// after\n// intervals[0] must be Value::Dictionary with Hour=3, Minute=0 — fix render_plist's interval emission order/type","handlingStrategy":"validation","validationCode":"let intervals = match dict.get(\"StartCalendarInterval\") {\n    Some(Value::Array(a)) => a,\n    v => panic!(\"StartCalendarInterval not array: {v:?}\"),\n};\nassert!(matches!(intervals.first(), Some(Value::Dictionary(_))),\n        \"first interval not dict: {:?}\", intervals.first());","typeGuard":"fn as_interval(v: &Value) -> Option<&PlistDictionary> {\n    match v { Value::Dictionary(d) if d.contains_key(\"Hour\") => Some(d), _ => None }\n}","tryCatchPattern":null,"preventionTips":["Preserve input ordering deterministically when serializing schedule lists","Add per-element type checks in the serializer so bad elements fail at render time","Test single-interval and multi-interval requests separately"],"tags":["rust","test-assertion","plist","launchd"],"backgroundTag":"unexpected-response-shape","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}