#7985·rustfs

MinIO-compatible /minio/admin/v3/datausageinfo returns snake_case fields, madmin-go DataUsageInfo() decodes all zeros (1.0.0)

Author: BianzinanCreated Sep 17, 2026Updated Sep 17, 2026

Describe the bug

On the MinIO-compatible admin path, GET /minio/admin/v3/datausageinfo returns the usage census with snake_case field names (buckets_usage, objects_count, objects_total_size, and last_update as a {secs_since_epoch, nanos_since_epoch} object). MinIO serves the same endpoint with camelCase names (bucketsUsageInfo, objectsCount, objectsTotalSize, and lastUpdate as an RFC 3339 string).

Clients built on madmin-go decode the MinIO shape, so against RustFS AdminClient.DataUsageInfo() returns a zero-valued DataUsageInfo without an error: no buckets, zero objects, zero bytes, LastUpdate = 0001-01-01T00:00:00Z. The census itself is correct — the raw response contains the expected numbers — only the field naming differs, so the failure is silent for callers.

The other MinIO-compatible admin calls we use decode fine with madmin-go against the same server: ServerInfo, AddServiceAccount (with an inline bucket policy), ListServiceAccounts, DeleteServiceAccount, SetBucketQuota (hard quota is enforced).

To Reproduce

  1. Start RustFS: docker run -d -p 19000:9000 -e RUSTFS_ACCESS_KEY=probeadmin -e RUSTFS_SECRET_KEY=probeadmin-secret rustfs/rustfs:1.0.0
  2. Create a bucket and put one 20 MiB object in it (any S3 client).
  3. Wait for a scanner cycle (default cycle is 60 s).
  4. Call the endpoint with madmin-go:
go
cl, _ := madmin.New("127.0.0.1:19000", "probeadmin", "probeadmin-secret", false)
info, err := cl.DataUsageInfo(context.Background())
fmt.Println(err, info.BucketsCount, info.ObjectsTotalCount, len(info.BucketsUsage), info.LastUpdate)
// RustFS 1.0.0: <nil> 0 0 0 0001-01-01 00:00:00 +0000 UTC
// MinIO (same objects): <nil>, non-zero counts, the bucket present in BucketsUsage, a real LastUpdate
  1. The raw signed response from RustFS (trimmed) shows the data is present:
json
{"total_capacity":954697216000,"last_update":{"secs_since_epoch":1789651409,"nanos_since_epoch":281440410},
 "scanner_cycle":5,"objects_total_count":2,"objects_total_size":20971522,"buckets_count":2,
 "buckets_usage":{"probe-b":{"size":20971520,"objects_count":1, ...}}}

The same request against MinIO RELEASE.2025-04-22T22-12-26Z (trimmed):

json
{"lastUpdate":"2026-09-17T13:27:42.923033731Z","objectsCount":5,"objectsTotalSize":20971819,"bucketsCount":5,
 "bucketsUsageInfo":{"probe-b":{"size":20971520,"objectsCount":1, ...}}}

Expected behavior

When the request comes in on the MinIO-compatible prefix (/minio/admin/v3/...), the datausageinfo body uses MinIO's field names and types, so madmin-go based tools (and anything else written against MinIO's admin API) read the usage census correctly. The native /rustfs/admin/v3/datausageinfo response could keep its current shape if that is intended.

If snake_case on the MinIO prefix is intentional, a note in the compatibility documentation would help, since the mismatch does not surface as an error.

Environment

  • RustFS: rustfs/rustfs:1.0.0 (Docker, single node, single volume /data)
  • Client: github.com/minio/madmin-go/v3 v3.0.110, github.com/minio/minio-go/v7 v7.0.98
  • Host: Ubuntu 24.04, x86_64

Additional context

The handler is registered in rustfs/src/admin/handlers/system.rs (DataUsageInfoHandler), serialising the usage struct with serde_json::to_vec, which keeps the Rust field names. We worked around it on the client side by fetching the raw JSON and accepting both namings, so this is not blocking for us; reporting it because other madmin-go users are likely to see silent zeros.