juicedata/juicefs · warning

mtime deviation is too large, the actual mtime is %s but got

Error message

mtime deviation is too large, the actual mtime is %s but got %s

What it means

objbench verifies that Chtimes took effect within a ±2 second tolerance: if the mtime returned by Head is before mtime-2s or after mtime+2s, this error fires. It means the backend did not store (or returned with drift) the requested modification time.

Source

Thrown at cmd/objbench.go:1137

			return fmt.Errorf("failed to head object %s", err)
		} else if info, ok := objInfo.(object.File); ok {
			if info.Mode()&0xFFF != 0777 {
				return fmt.Errorf("expect mode %o but got %o", 0777, info.Mode())
			}
		}
		return nil
	})

	funFSCase("change mtime", func() error {
		mtime := time.Now().Add(-10 * time.Minute)
		if err := fi.Chtimes(key, mtime); err != nil {
			return fmt.Errorf("failed to chtimes %s", err)
		}
		if objInfo, err := blob.Head(ctx, key); err != nil {
			return fmt.Errorf("failed to head object %s", err)
		} else {
			if objInfo.Mtime().Before(mtime.Add(-2*time.Second)) || objInfo.Mtime().After(mtime.Add(2*time.Second)) {
				return fmt.Errorf("mtime deviation is too large, the actual mtime is %s but got %s", mtime.Format(time.RFC3339), objInfo.Mtime().Format(time.RFC3339))
			}
		}
		return nil
	})
}

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Use a backend that persists custom mtime metadata (e.g. stores mtime as object metadata like x-amz-meta-mtime).
  2. Sync clocks (NTP) between client and storage nodes.
  3. Rerun Head after a short delay to rule out eventual-consistency staleness.
  4. Accept reduced precision on backends with second-granularity mtimes; treat ±2s tolerance failures as backend limitation.

Example fix

// before
mtime := time.Now().Add(-10 * time.Minute)
if err := fi.Chtimes(key, mtime); err != nil {
// after: verify backend supports Chtimes first, and log returned mtime
mtime := time.Now().Add(-10 * time.Minute).Truncate(time.Second)
if err := fi.Chtimes(key, mtime); err != nil {
Defensive patterns

Strategy: validation

Validate before calling

if !backend.SupportsSetMtime() {
    return nil // skip mtime verification
}

Try / catch

if objInfo.Mtime().Before(mtime.Add(-2*time.Second)) || objInfo.Mtime().After(mtime.Add(2*time.Second)) {
    log.Warnf("mtime drift on %s: want %s got %s", key, mtime, objInfo.Mtime())
    return nil
}

Prevention

When it happens

Trigger: fi.Chtimes(key, now-10min) succeeds, Head returns objInfo.Mtime() outside [mtime-2s, mtime+2s] — e.g. backend ignores Chtimes and reports upload time, or clock skew between client and server timestamps.

Common situations: Backends that silently ignore SetMtime; systems with large NTP clock skew; stores that round or truncate mtimes to whole seconds/minutes; eventual-consistency returning stale metadata.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/1bedd4de3c644cb6. Report an issue: GitHub.