{"record":{"id":"af91b36d04abafb2","repo":"spacedriveapp/spacedrive","slug":"invalid-duration-format","errorCode":null,"errorMessage":"Invalid duration format: {}","messagePattern":"Invalid duration format: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"apps/cli/src/domains/sync/mod.rs","lineNumber":156,"sourceCode":"\t\tlet duration = parse_duration(duration_str)?;\n\t\tOk(Utc::now() - duration)\n\t} else {\n\t\t// Try parsing as absolute time\n\t\tDateTime::parse_from_rfc3339(time_str)\n\t\t\t.map(|dt| dt.with_timezone(&Utc))\n\t\t\t.or_else(|_| {\n\t\t\t\t// Try common formats\n\t\t\t\tDateTime::parse_from_str(time_str, \"%Y-%m-%d %H:%M:%S\")\n\t\t\t\t\t.map(|dt| dt.with_timezone(&Utc))\n\t\t\t})\n\t\t\t.map_err(|_| anyhow::anyhow!(\"Invalid time format: {}\", time_str))\n\t}\n}\n\nfn parse_duration(duration_str: &str) -> Result<chrono::Duration> {\n\tlet parts: Vec<&str> = duration_str.split_whitespace().collect();\n\tif parts.len() != 2 {\n\t\treturn Err(anyhow::anyhow!(\"Invalid duration format: {}\", duration_str));\n\t}\n\n\tlet value: i64 = parts[0]\n\t\t.parse()\n\t\t.map_err(|_| anyhow::anyhow!(\"Invalid number: {}\", parts[0]))?;\n\tlet unit = parts[1].to_lowercase();\n\n\tlet seconds = match unit.as_str() {\n\t\t\"second\" | \"seconds\" | \"sec\" | \"s\" => value,\n\t\t\"minute\" | \"minutes\" | \"min\" | \"m\" => value * 60,\n\t\t\"hour\" | \"hours\" | \"h\" => value * 3600,\n\t\t\"day\" | \"days\" | \"d\" => value * 86400,\n\t\t\"week\" | \"weeks\" | \"w\" => value * 604800,\n\t\t_ => return Err(anyhow::anyhow!(\"Unknown time unit: {}\", unit)),\n\t};\n\n\tOk(chrono::Duration::seconds(seconds))\n}","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/apps/cli/src/domains/sync/mod.rs#L138-L174","documentation":"Thrown by parse_duration() when the duration part of an 'ago' expression does not split (on whitespace) into exactly two tokens: a number and a unit. It is reached from parse_time_filter() after stripping the trailing ' ago' (4 characters), so '10 minutes ago' -> '10 minutes' parses, while malformed remainders do not.","triggerScenarios":"--since '5minutes ago' (no space), '--since \"5  minutes ago\"' (double space yields 3 tokens), '--since ago' (empty remainder), or any extra words like '--since \"about 5 minutes ago\"' (3 tokens).","commonSituations":"Shell quoting that collapses or mangles spaces; users adding filler words; trailing whitespace inside the quoted string.","solutions":["Use exactly one space between number and unit: --since '5 minutes ago'","Remove filler words and extra whitespace from the expression","Switch to an absolute timestamp if spacing is hard to control in your shell"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let tokens: Vec<&str> = duration_str.split_whitespace().collect();\nif tokens.len() != 2 {\n    eprintln!(\"Duration must be exactly '<number> <unit>', e.g. '30 minutes'\");\n    return Ok(());\n}","typeGuard":"fn is_wellformed_duration(d: &str) -> bool {\n    let mut it = d.split_whitespace();\n    matches!((it.next(), it.next(), it.next()), (Some(_), Some(_), None))\n}","tryCatchPattern":null,"preventionTips":["Use exactly one space between number and unit in 'ago' expressions","Avoid filler words ('about', 'roughly') inside the duration","Normalize whitespace (split_whitespace + rejoin) before passing user input through"],"tags":["cli","sync","time-parsing","duration"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}