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
- Use a backend that persists custom mtime metadata (e.g. stores mtime as object metadata like x-amz-meta-mtime).
- Sync clocks (NTP) between client and storage nodes.
- Rerun Head after a short delay to rule out eventual-consistency staleness.
- 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
- Use backends that persist mtime metadata (e.g. x-amz-meta-mtime style).
- Keep client clocks NTP-synced to avoid skew.
- Truncate target mtime to whole seconds on second-granularity stores.
- Allow a retry delay for eventually-consistent metadata.
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
- failed to chtimes %s
- ErrNotSUP
- failed to get the first byte:, expect "h", but got %q, error
- failed to get the last byte: expect "o", but got %q, error:
- failed to get the last three bytes: expect "llo", but got %q
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/1bedd4de3c644cb6.
Report an issue: GitHub.