{"record":{"id":"9b05493d97875cb4","repo":"gitbutlerapp/gitbutler","slug":"suppression-duration-must-be-at-least-1-hour","errorCode":null,"errorMessage":"Suppression duration must be at least 1 hour","messagePattern":"Suppression duration must be at least 1 hour","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-update/src/cache.rs","lineNumber":126,"sourceCode":"/// * `Err(_)` - An error occurred:\n///   - Invalid hours value (must be 1-720)\n///   - No cached update check exists\n///   - The cached status shows the app is already up to date\n///   - Failed to write the updated cache\n///\n/// # Errors\n///\n/// Returns an error if:\n/// - The hours parameter is 0 or greater than 720 (30 days)\n/// - No update check has been performed yet (no cache exists)\n/// - The current version is already up to date (nothing to suppress)\n/// - The cache cannot be written\npub fn suppress_update(cache: &mut but_db::AppCacheHandle, hours: u32) -> anyhow::Result<()> {\n    // Validate input\n    const MAX_SUPPRESSION_HOURS: u32 = 720; // 30 days\n\n    if hours == 0 {\n        anyhow::bail!(\"Suppression duration must be at least 1 hour\");\n    }\n\n    if hours > MAX_SUPPRESSION_HOURS {\n        anyhow::bail!(\"Suppression duration cannot exceed {MAX_SUPPRESSION_HOURS} hours (30 days)\");\n    }\n\n    cache\n        .update_check_mut()?\n        .suppress(hours)\n        .map_err(Into::into)\n}\n","sourceCodeStart":108,"sourceCodeEnd":138,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-update/src/cache.rs#L108-L138","documentation":"`suppress_update` in but-update's cache module validates the requested auto-update suppression duration before persisting it. A value of 0 hours is meaningless (nothing would be suppressed) and is rejected immediately with this bail!.","triggerScenarios":"Calling `suppress_update(cache, 0)`, or a UI/config path that computes a 0-hour duration (e.g. an expired or zero-valued \"remind me later\" setting).","commonSituations":"A settings dialog defaulting to 0 before the user picks a value; computing hours from timestamps that yield 0; deserializing a stored suppression preference of `0`.","solutions":["Pass a duration of at least 1 hour, e.g. `suppress_update(cache, 1)`.","Clamp the computed value before calling: `let hours = hours.max(1);`.","Fix the caller that produces 0 (default the UI selector to a sane minimum like 24h)."],"exampleFix":"// before\nsuppress_update(&mut cache, user_hours).await?;\n// after\nsuppress_update(&mut cache, user_hours.max(1)).await?;","handlingStrategy":"validation","validationCode":"if hours == 0 { return Err(\"suppression must be at least 1 hour\"); }\nsuppress_update(&mut cache, hours)?;","typeGuard":null,"tryCatchPattern":"// Rust\nmatch suppress_update(&mut cache, hours) {\n    Err(e) if e.to_string().contains(\"at least 1 hour\") => {\n        eprintln!(\"choose a duration >= 1h\");\n    }\n    r => r?,\n}","preventionTips":["Clamp computed durations with `.max(1)` before calling.","Default UI selectors to a positive minimum (e.g. 24h).","Validate stored preferences on load and discard zero values."],"tags":["update-check","validation","range-check","cache"],"backgroundTag":"value-out-of-range","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}