{"record":{"id":"6e679a8e36f4a952","repo":"astrid-runtime/astrid","slug":"retain-bytes-must-be-greater-than-0","errorCode":null,"errorMessage":"--retain-bytes must be greater than 0","messagePattern":"--retain-bytes must be greater than 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/audit.rs","lineNumber":110,"sourceCode":"    let format = ValueFormat::parse(&args.format);\n    if format.is_pretty() {\n        print_stats_pretty(&stats, &health);\n    } else {\n        emit_structured(&AuditStatsOutput { stats, health }, format)?;\n    }\n    Ok(if degraded {\n        ExitCode::from(2)\n    } else {\n        ExitCode::SUCCESS\n    })\n}\n\nasync fn run_prune(args: &AuditPruneArgs) -> Result<ExitCode> {\n    if args.retain_entries == 0 {\n        bail!(\"--retain-entries must be at least 1\");\n    }\n    if args.retain_bytes == Some(0) {\n        bail!(\"--retain-bytes must be greater than 0\");\n    }\n    let mut client = connect_as_active_agent().await?;\n    let body = into_result(\n        client\n            .request(AdminRequestKind::AuditPrune {\n                retain_entries: args.retain_entries,\n                retain_bytes: args.retain_bytes,\n            })\n            .await?,\n    )?;\n    let AdminResponseBody::AuditPruned(result) = body else {\n        bail!(\"unexpected response from kernel: {body:?}\");\n    };\n    let format = ValueFormat::parse(&args.format);\n    if format.is_pretty() {\n        print_prune_pretty(&result);\n    } else {\n        emit_structured(&result, format)?;","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/audit.rs#L92-L128","documentation":"In `run_prune` (crates/astrid-cli/src/commands/audit.rs:110), the CLI rejects `--retain-bytes 0` with bail! before issuing the AuditPrune request. A zero byte cap would prune everything, so it is treated as an invalid argument rather than a no-op.","triggerScenarios":"Running `astrid-cli audit prune --retain-bytes 0` (Option<u64> set to Some(0)), typically from a script computing a byte budget that ended up 0.","commonSituations":"Automation computing a retention byte budget from a quota that is currently 0; typo passing 0 instead of omitting the flag (None = unlimited by bytes); confusion between 'no limit' and 'zero limit'.","solutions":["Pass --retain-bytes with a value >= 1, or omit the flag entirely if byte-based retention is not wanted","In scripts, guard the computed budget before invoking the CLI","Use a large sentinel value rather than 0 if the intent is 'keep nearly nothing but not everything'"],"exampleFix":"// before\nastrid audit prune --retain-bytes 0\n// after\n# omit the flag (no byte limit) or use a positive value:\nastrid audit prune --retain-bytes 1048576","handlingStrategy":"validation","validationCode":"#!/usr/bin/env bash\nif [ -n \"$RETAIN_BYTES\" ] && [ \"$RETAIN_BYTES\" -eq 0 ]; then\n  echo \"--retain-bytes must be greater than 0 (or omit the flag)\" >&2; exit 64\nfi\nastrid audit prune --retain-bytes \"${RETAIN_BYTES:+$RETAIN_BYTES}\"","typeGuard":null,"tryCatchPattern":"match astrid::commands::audit::run_prune(&args).await {\n    Ok(code) => code,\n    Err(e) if e.to_string().contains(\"--retain-bytes\") => {\n        eprintln!(\"invalid retention: {e:#}\");\n        ExitCode::from(64)\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Omit --retain-bytes entirely for no byte cap instead of passing 0","Guard computed byte budgets in scripts so they cannot be 0","Document that 0 means 'invalid' (would prune everything), not 'unlimited'","Add unit tests for prune argument validation"],"tags":["cli","validation","argument","audit"],"backgroundTag":"invalid-flag-value","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}