block/buzz · critical · anyhow::Error

failed to initialize media storage

Error message

failed to initialize media storage: {e}

What it means

Fatal startup error: buzz_media::MediaStorage::new() failed while standing up media storage from config.media (after validate() already passed). This step constructs the S3/MinIO client against the configured endpoint, bucket, credentials, region, and addressing style — failures here are connectivity, credentials, bucket, or endpoint-shape problems.

Solutions

  1. Verify the endpoint and bucket from the same host: aws --endpoint-url $BUZZ_MEDIA_S3_ENDPOINT s3 ls s3://$BUZZ_MEDIA_S3_BUCKET (or mc for MinIO)
  2. Create the bucket if missing, or fix its name
  3. Update credentials/region: region must match the endpoint's region for real AWS S3
  4. Check the addressing style matches your S3 implementation (path-style for MinIO)
  5. Restart the relay once storage checks pass

Example fix

# before
export BUZZ_MEDIA_S3_ENDPOINT=http://minio:9000
export BUZZ_MEDIA_S3_BUCKET=media
# bucket never created -> init fails

# after
mc alias set local http://minio:9000 $MINIO_ROOT_USER $MINIO_ROOT_PASSWORD
mc mb local/media
export BUZZ_MEDIA_S3_ENDPOINT=http://minio:9000
export BUZZ_MEDIA_S3_BUCKET=media
Defensive patterns

Strategy: validation

Validate before calling

# Boot gate: prove bucket access with the same coordinates the relay uses:
aws --endpoint-url "$BUZZ_MEDIA_S3_ENDPOINT" s3 ls "s3://${BUZZ_MEDIA_S3_BUCKET:?}" >/dev/null \
  || { echo 'media bucket unreachable'; exit 1; }

Try / catch

// Retry startup only for transient S3 outages; credential/bucket errors are
// configuration fixes followed by a restart.

Prevention

When it happens

Trigger: S3 endpoint unreachable or wrong (self-hosted MinIO down / wrong port), the bucket does not exist, credentials are rejected, path-style vs virtual-host addressing mismatch, or an AWS region that does not match the endpoint so signatures are scoped wrong.

Common situations: MinIO container not up when the relay boots; bucket name typo; rotating S3 keys without updating the relay secret; switching between path-style (MinIO default) and virtual-host style without DNS to match.

Related errors


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

Appendix: source

Thrown at crates/buzz-relay/src/main.rs:514

        .connect(search_db_url)
        .await
        .map_err(|e| anyhow::anyhow!("Search DB connection failed: {e}"))?;
    let search_metrics_pool = search_pool.clone();
    let search = SearchService::new(search_pool);
    info!(
        replica = config.read_database_url.is_some(),
        "Search service ready (Postgres FTS)"
    );

    let workflow_config = buzz_workflow::WorkflowConfig::default();
    let workflow_engine = Arc::new(WorkflowEngine::new(db.clone(), workflow_config));

    config
        .media
        .validate()
        .map_err(|e| anyhow::anyhow!("invalid media config: {e}"))?;
    let media_storage = buzz_media::MediaStorage::new(&config.media)
        .map_err(|e| anyhow::anyhow!("failed to initialize media storage: {e}"))?;
    info!("Media storage connected");

    let (app_state, audit_shutdown) = AppState::new(
        config.clone(),
        db,
        redis_health_pool,
        audit,
        pubsub,
        auth,
        search,
        Arc::clone(&workflow_engine),
        relay_keypair,
        media_storage,
    );
    let state = Arc::new(app_state);

    // Inter-relay mesh (BUZZ_MESH seam). `boot_mesh` returns None when the
    // kill switch is off — nothing is bound, published, or spawned, so the

View on GitHub (pinned to ef2aa1ae38)