block/buzz · error · anyhow::Error

--max-objects must be greater than zero

Error message

--max-objects must be greater than zero

What it means

The storage-snapshot command requires a positive object cap; --max-objects 0 would make the bucket-listing fold a no-op and persist an empty snapshot. The guard rejects zero explicitly after the i64 range check.

Solutions

  1. Pass a positive value, e.g. --max-objects 1000000.
  2. Fix scripts so an unset/empty cap variable defaults to a sane positive number instead of 0.
  3. There is no 'unlimited' mode via 0; choose a very large positive cap if a bound is not desired.

Example fix

// before
buzz-admin storage-snapshot --max-objects 0
// after
buzz-admin storage-snapshot --max-objects 1000000
Defensive patterns

Strategy: validation

Validate before calling

if max_objects == 0 {
    return Err("--max-objects must be a positive integer".into());
}

Type guard

fn is_positive(v: u64) -> bool { v > 0 }

Prevention

When it happens

Trigger: Invoking `buzz-admin storage-snapshot --max-objects 0`. The u64 parses fine and the i64 conversion succeeds, but the `max_objects == 0` check fires.

Common situations: A shell script defaulting an unset variable to 0 (`--max-objects ${MAX_OBJECTS:-0}`), or a user assuming 0 means 'no limit'.

Understand the failure class

Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.

Related errors


AI-assisted analysis of block/buzz@ef2aa1ae38 (2026-09-20). Data as JSON: /api/errors/04e1d036aa082a3e. Report an issue: GitHub.

Appendix: source

Thrown at crates/buzz-admin/src/main.rs:186

        Command::AddMember { pubkey, role } => cmd_add_member(pubkey, role).await,
        Command::RemoveMember { pubkey, role } => cmd_remove_member(pubkey, role).await,
        Command::ListMembers => cmd_list_members().await,
        Command::ProductFeedback {
            command: ProductFeedbackCommand::List { limit },
        } => cmd_list_product_feedback(limit).await,
        Command::Deletions { command } => deletions::run(command).await,
        Command::ReconcileChannels { channel, relay_key } => {
            reconcile_channels(channel, relay_key).await?;
            Ok(0)
        }
    }
}

async fn cmd_storage_snapshot(max_objects: u64) -> Result<i32> {
    let max_objects_db = i64::try_from(max_objects)
        .map_err(|_| anyhow::anyhow!("--max-objects must be at most {}", i64::MAX))?;
    if max_objects == 0 {
        return Err(anyhow::anyhow!("--max-objects must be greater than zero"));
    }

    let db = connect_db().await?;
    let mut leader = db.try_lock_storage_accounting().await?.ok_or_else(|| {
        anyhow::anyhow!("another storage-snapshot worker already holds the lease")
    })?;
    let storage = Arc::new(MediaStorage::new(&storage_config_from_env()?)?);
    let code_sha =
        std::env::var("BUZZ_STORAGE_SNAPSHOT_CODE_SHA").unwrap_or_else(|_| "unknown".to_string());
    if code_sha.is_empty() || code_sha.len() > 128 {
        return Err(anyhow::anyhow!(
            "BUZZ_STORAGE_SNAPSHOT_CODE_SHA must contain 1 to 128 bytes"
        ));
    }

    println!(
        "{}",
        serde_json::json!({

View on GitHub (pinned to ef2aa1ae38)