jdx/mise · error

expected first calendar interval dictionary, got {value:?}

Error message

expected first calendar interval dictionary, got {value:?}

What it means

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.

Source

Thrown at src/system/launchd.rs:868

            working_directory: None,
            stdout_path: None,
            stderr_path: None,
            kickstart: false,
        };
        let plist = render_plist(&request).unwrap();
        let dict = match Value::from_reader_xml(Cursor::new(plist.as_slice())).unwrap() {
            Value::Dictionary(dict) => dict,
            value => panic!("expected dictionary, got {value:?}"),
        };
        match dict.get("StartCalendarInterval") {
            Some(Value::Array(intervals)) => {
                assert_eq!(intervals.len(), 2);
                match &intervals[0] {
                    Value::Dictionary(interval) => {
                        assert_eq!(interval.get("Hour"), Some(&Value::Integer(3.into())));
                        assert_eq!(interval.get("Minute"), Some(&Value::Integer(0.into())));
                    }
                    value => panic!("expected first calendar interval dictionary, got {value:?}"),
                }
                match &intervals[1] {
                    Value::Dictionary(interval) => {
                        assert_eq!(interval.get("Hour"), Some(&Value::Integer(12.into())));
                        assert_eq!(interval.get("Weekday"), Some(&Value::Integer(1.into())));
                    }
                    value => panic!("expected second calendar interval dictionary, got {value:?}"),
                }
            }
            value => panic!("expected StartCalendarInterval array, got {value:?}"),
        }
        assert_eq!(dict.get("ThrottleInterval"), None);
        assert_eq!(dict.get("QueueDirectories"), None);
    }

    #[test]
    fn test_render_plist_throttle_and_queue_directories() {
        let request = LaunchdRequest::from_toml(

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Inspect intervals[0] via the {value:?} panic payload
  2. Verify render_plist preserves request calendar-interval ordering and emits each interval as a dictionary with Hour/Minute/Weekday keys
  3. Fix the serializer or reorder the test data so the daily 3:00 interval is first

Example fix

// before
value => panic!("expected first calendar interval dictionary, got {value:?}"),
// after
// intervals[0] must be Value::Dictionary with Hour=3, Minute=0 — fix render_plist's interval emission order/type
Defensive patterns

Strategy: validation

Validate before calling

let intervals = match dict.get("StartCalendarInterval") {
    Some(Value::Array(a)) => a,
    v => panic!("StartCalendarInterval not array: {v:?}"),
};
assert!(matches!(intervals.first(), Some(Value::Dictionary(_))),
        "first interval not dict: {:?}", intervals.first());

Type guard

fn as_interval(v: &Value) -> Option<&PlistDictionary> {
    match v { Value::Dictionary(d) if d.contains_key("Hour") => Some(d), _ => None }
}

Prevention

When it happens

Trigger: 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).

Common situations: Reordering interval emission, serializing intervals as arrays of scalars, or a change that puts the weekday-based interval first.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/6068b0ba88602d44. Report an issue: GitHub.