jdx/mise · error

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

Error message

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

What it means

Test assertion panic in test_render_plist_multiple_calendar_intervals. The test requires the second StartCalendarInterval entry to be a dictionary with Hour=12 and Weekday=1; if intervals[1] is not a dictionary, this catch-all arm panics with the actual value.

Source

Thrown at src/system/launchd.rs:875

            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(
            "sync".to_string(),
            LaunchdTomlConfig {
                program: Some("/bin/echo".to_string()),
                throttle_interval: Some(10),
                nice: None,
                queue_directories: vec![
                    "~/Library/Queues/sync".to_string(),

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Inspect intervals[1] in the {value:?} panic payload
  2. Ensure every StartCalendarInterval element is serialized as a plist dictionary even when it only has Hour/Weekday keys
  3. Fix render_plist or update the test to match the intended schema

Example fix

// before
value => panic!("expected second calendar interval dictionary, got {value:?}"),
// after
// intervals[1] must be Value::Dictionary with Hour=12, Weekday=1
Defensive patterns

Strategy: validation

Validate before calling

let second = intervals.get(1)
    .unwrap_or_else(|| panic!("missing second interval"));
assert!(matches!(second, Value::Dictionary(_)), "second interval not dict: {second:?}");

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 the second calendar interval as a non-dictionary, or emits only one interval so the surrounding array match has already failed differently; here specifically intervals[1] has the wrong type.

Common situations: Changes to interval serialization that flatten scalar-only intervals (e.g. weekday-only schedules) into non-dict plist values.

Related errors


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