Zackriya-Solutions/meetily · info
metadata value checked as object
Error message
metadata value checked as object
What it means
serde_json's Value::as_object_mut() returns Some only when the root value is a JSON object. The code checks value.is_object() and bails with a proper error otherwise, so the .expect("metadata value checked as object") is a correctly defended invariant — reachable only if future edits mutate value's variant between the check and the use.
Source
Thrown at frontend/src-tauri/src/summary/metadata.rs:80
summary_language: Option<&str>,
) -> Result<()> {
let _guard = METADATA_WRITE_LOCK.lock().unwrap_or_else(|poisoned| poisoned.into_inner());
let metadata_path = metadata_path(folder);
let temp_path = metadata_temp_path(folder);
let mut value = if metadata_path.exists() {
let raw = std::fs::read_to_string(&metadata_path)
.with_context(|| format!("Failed to read {}", metadata_path.display()))?;
parse_metadata_json(&raw)?
} else {
Value::Object(serde_json::Map::new())
};
if !value.is_object() {
bail!("Failed to parse metadata.json: root value must be a JSON object");
}
let object = value.as_object_mut().expect("metadata value checked as object");
match summary_language {
Some(code) => {
let normalised = normalise_supported_summary_language(code)?;
object.insert(field.to_string(), Value::String(normalised));
}
None => {
object.remove(field);
}
}
let json_string = serde_json::to_string_pretty(&value)
.context("Failed to serialize metadata.json")?;
std::fs::write(&temp_path, json_string)
.with_context(|| format!("Failed to write {}", temp_path.display()))?;
std::fs::rename(&temp_path, &metadata_path).with_context(|| {
format!(
"Failed to replace {} with {}",
metadata_path.display(),View on GitHub (pinned to 0281737d87)
Solutions
- None required — the guard is already correct
- Optionally make the narrowing explicit with let-else: `let Value::Object(object) = &mut value else { bail!(...) };`
- Keep the is_object check directly adjacent to the as_object_mut call in future edits
Example fix
// after (idiomatic narrowing, no expect)
let Value::Object(object) = &mut value else {
bail!("Failed to parse metadata.json: root value must be a JSON object");
}; Defensive patterns
Strategy: type-guard
Validate before calling
if !value.is_object() {
anyhow::bail!("metadata.json root must be a JSON object");
} Type guard
fn is_json_object(v: &serde_json::Value) -> bool {
v.is_object()
} Prevention
- Keep the is_object check immediately before as_object_mut; never split them across calls
- Prefer let-else narrowing (`let Value::Object(o) = ... else`) to make invalid states unrepresentable
- Validate external JSON at the boundary (parse_metadata_json) so downstream code can assume the shape
When it happens
Trigger: Only via a refactor that reassigns `value` (or calls code that can) between the is_object() check and the expect; as written the two lines are adjacent and the panic is unreachable.
Common situations: Never observed; this check-then-expect pairing is the recommended pattern for narrowing serde_json roots without cloning.
Related errors
- Buffer should always be available
- Invalid regex pattern
- At least one model must be defined
- Meeting metadata not found
- Unknown sample rate
AI-assisted analysis of Zackriya-Solutions/meetily@0281737d87 (2026-08-16).
Data as JSON: /api/errors/e6ff479c99738f45.
Report an issue: GitHub.