{"record":{"id":"62a9cf44ed632905","repo":"block/buzz","slug":"name-must-be-set-for-storage-snapshot","errorCode":null,"errorMessage":"{name} must be set for storage-snapshot","messagePattern":"(.+?) must be set for storage-snapshot","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/buzz-admin/src/main.rs","lineNumber":292,"sourceCode":"    fold: FoldFuture,\n    persist: Persist,\n) -> Result<(BucketSnapshot, i64)>\nwhere\n    FoldFuture: Future<Output = std::result::Result<BucketSnapshot, SweepError>>,\n    Persist: FnOnce(serde_json::Value, i64) -> PersistFuture,\n    PersistFuture: Future<Output = Result<()>>,\n{\n    let started = Instant::now();\n    let snapshot = fold.await?;\n    let duration_ms = i64::try_from(started.elapsed().as_millis()).unwrap_or(i64::MAX);\n    let encoded = serde_json::to_value(&snapshot)?;\n    persist(encoded, duration_ms).await?;\n    Ok((snapshot, duration_ms))\n}\n\nfn storage_config_from_env() -> Result<MediaConfig> {\n    let required = |name: &str| {\n        std::env::var(name).map_err(|_| anyhow::anyhow!(\"{name} must be set for storage-snapshot\"))\n    };\n    let addressing_style = std::env::var(\"BUZZ_S3_ADDRESSING_STYLE\")\n        .unwrap_or_else(|_| \"path\".to_string())\n        .parse::<S3AddressingStyle>()\n        .map_err(anyhow::Error::msg)?;\n    Ok(MediaConfig {\n        s3_endpoint: std::env::var(\"BUZZ_S3_ENDPOINT\").unwrap_or_default(),\n        s3_access_key: std::env::var(\"BUZZ_S3_ACCESS_KEY\").unwrap_or_default(),\n        s3_secret_key: std::env::var(\"BUZZ_S3_SECRET_KEY\").unwrap_or_default(),\n        s3_bucket: required(\"BUZZ_S3_BUCKET\")?,\n        s3_region: std::env::var(\"BUZZ_S3_REGION\").unwrap_or_else(|_| \"us-east-1\".to_string()),\n        s3_addressing_style: addressing_style,\n        max_image_bytes: 1,\n        max_gif_bytes: 1,\n        max_video_bytes: 1,\n        max_file_bytes: 1,\n        public_base_url: \"http://storage-snapshot.invalid/media\".to_string(),\n        upload_records_enabled: false,","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/block/buzz/blob/ef2aa1ae38fadcc0bc22b8bf6ed96b35933146be/crates/buzz-admin/src/main.rs#L274-L310","documentation":"storage_config_from_env builds the S3 MediaConfig for the snapshot and requires BUZZ_S3_BUCKET to be present in the environment; unlike endpoint/keys/region it has no default. The `required` closure maps a failed std::env::var lookup to this error naming the missing variable.","triggerScenarios":"Running `buzz-admin storage-snapshot` without BUZZ_S3_BUCKET exported (and, in practice, the other S3 settings also unset, since the bucket is the only hard-required one). std::env::var(\"BUZZ_S3_BUCKET\") returns Err (missing or non-UTF8) and the closure formats this message.","commonSituations":"Running the admin command in a shell where .env was not sourced, running via cron/systemd with a minimal environment, or forgetting that storage-snapshot needs media config even though it only lists the bucket.","solutions":["Export BUZZ_S3_BUCKET (and endpoint/keys: BUZZ_S3_ENDPOINT, BUZZ_S3_ACCESS_KEY, BUZZ_S3_SECRET_KEY) before running the command, e.g. `set -a; . ./.env; set +a`.","Run the command in the same environment/worker as the relay so its env is inherited.","Fix the service unit/cron file to include an EnvironmentFile with the media settings.","Read the error's {name} to confirm exactly which variable is missing, then set it."],"exampleFix":"// before\nbuzz-admin storage-snapshot --max-objects 1000000\n// after (load .env first)\nset -a; . ./.env; set +a\nbuzz-admin storage-snapshot --max-objects 1000000","handlingStrategy":"validation","validationCode":"for var in [\"BUZZ_S3_BUCKET\", \"BUZZ_S3_ENDPOINT\", \"BUZZ_S3_ACCESS_KEY\", \"BUZZ_S3_SECRET_KEY\"] {\n    if std::env::var(var).is_err() {\n        return Err(format!(\"{var} must be set for storage-snapshot\"));\n    }\n}","typeGuard":null,"tryCatchPattern":"match cmd_storage_snapshot(max_objects).await {\n    Err(e) if e.to_string().ends_with(\"must be set for storage-snapshot\") => {\n        eprintln!(\"Hint: source .env before running, e.g. `set -a; . ./.env; set +a`\");\n        return Err(e);\n    }\n    other => other?,\n}","preventionTips":["Source .env (set -a; . ./.env; set +a) in every shell or wrapper that runs buzz-admin.","For cron/systemd, use EnvironmentFile= or export the vars in the unit/script.","Keep the admin runner in the same environment as the relay so media config is inherited.","Pre-flight-check required env vars in deploy scripts before launching the command."],"tags":["environment","configuration","s3","missing-variable"],"backgroundTag":"missing-env-var","analyzedSha":"ef2aa1ae38fadcc0bc22b8bf6ed96b35933146be","analyzedAt":"2026-09-20T04:38:17.397Z","contentChangedAt":"2026-09-20T04:38:17.397Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}