jdx/mise · error
expected StartCalendarInterval array, got {value:?}
Error message
expected StartCalendarInterval array, got {value:?} What it means
Test assertion panic in test_render_plist_multiple_calendar_intervals. When a request carries two calendar schedules, the rendered plist must expose them as an array under 'StartCalendarInterval'; if the key is missing or holds a single dictionary/other type, this panic fires with the actual value.
Source
Thrown at src/system/launchd.rs:878
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(),
"/var/spool/sync".to_string(),
],
..Default::default()View on GitHub (pinned to afd2eddd3a)
Solutions
- Inspect the {value:?} payload to see what render_plist emitted for StartCalendarInterval
- Make render_plist emit an array of interval dictionaries when more than one schedule exists (launchd accepts a single dict only for one schedule)
- Re-run the test to confirm both intervals appear with correct Hour/Minute/Weekday keys
Example fix
// before "StartCalendarInterval" => Value::Dictionary(interval) // after "StartCalendarInterval" => Value::Array(intervals) // when request.calendar_intervals.len() > 1
Defensive patterns
Strategy: validation
Validate before calling
match dict.get("StartCalendarInterval") {
Some(Value::Array(a)) if a.len() > 1 => {},
Some(Value::Dictionary(_)) | None => panic!(
"multi-schedule request must render StartCalendarInterval as array, got {:?}",
dict.get("StartCalendarInterval")
),
other => panic!("unexpected StartCalendarInterval: {other:?}"),
} Type guard
fn is_multi_interval(v: Option<&Value>) -> bool {
matches!(v, Some(Value::Array(a)) if a.len() > 1)
} Prevention
- Remember launchd accepts a bare dict only for one schedule; arrays for many — encode that rule in the serializer
- Add a unit test asserting the dict-vs-array switch at the len()==1 boundary
When it happens
Trigger: render_plist serializes a two-interval request as a single StartCalendarInterval dictionary instead of an array (or omits the key), so dict.get("StartCalendarInterval") is not Some(Value::Array(_)).
Common situations: A refactor that always writes StartCalendarInterval as a bare dictionary (valid for a single schedule but wrong for multiple), regressing launchd's multi-interval array form.
Related errors
- expected dictionary, got {value:?}
- expected StartCalendarInterval dictionary, got {value:?}
- expected ProgramArguments array, got {value:?}
- expected EnvironmentVariables dictionary, got {value:?}
- expected first calendar interval dictionary, got {value:?}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/d1484c7d33a03966.
Report an issue: GitHub.