{"record":{"id":"c637a3d5cd65040b","repo":"juicedata/juicefs","slug":"mtime-of-key-should-be-within-30-seconds-but-got","errorCode":null,"errorMessage":"mtime of key should be within 30 seconds, but got %s","messagePattern":"mtime of key should be within 30 seconds, but got (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/objbench.go","lineNumber":909,"sourceCode":"\t\t\tif err == nil {\n\t\t\t\tif len(objs) != 2 {\n\t\t\t\t\treturn fmt.Errorf(\"list should return 2 keys, but got %d\", len(objs))\n\t\t\t\t}\n\t\t\t\tif objs[0].Key() != \"\" {\n\t\t\t\t\treturn fmt.Errorf(\"first key should be empty string, but got %s\", objs[0].Key())\n\t\t\t\t}\n\t\t\t\tif objs[0].Size() != 0 {\n\t\t\t\t\treturn fmt.Errorf(\"first object size should be 0, but got %d\", objs[0].Size())\n\t\t\t\t}\n\t\t\t\tif objs[1].Key() != key {\n\t\t\t\t\treturn fmt.Errorf(\"first key should be test, but got %s\", objs[1].Key())\n\t\t\t\t}\n\t\t\t\tif objs[1].Size() != 5 {\n\t\t\t\t\treturn fmt.Errorf(\"size of first key shold be 5, but got %v\", objs[1].Size())\n\t\t\t\t}\n\t\t\t\tnow := time.Now()\n\t\t\t\tif objs[1].Mtime().Before(now.Add(-30*time.Second)) || objs[1].Mtime().After(now.Add(time.Second*30)) {\n\t\t\t\t\treturn fmt.Errorf(\"mtime of key should be within 30 seconds, but got %s\", objs[1].Mtime().Sub(now))\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn fmt.Errorf(\"list failed: %s\", err)\n\t\t\t}\n\n\t\t\tobjs, err = listAll(ctx, blob, \"\", \"test2\", 1)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"list failed: %s\", err)\n\t\t\t} else if len(objs) != 0 {\n\t\t\t\treturn fmt.Errorf(\"list should not return anything, but got %d\", len(objs))\n\t\t\t}\n\t\t} else {\n\t\t\tobjs, err2 := listAll(ctx, blob, \"\", \"\", 1)\n\t\t\tif err2 == nil {\n\t\t\t\tif len(objs) != 1 {\n\t\t\t\t\treturn fmt.Errorf(\"list should return 1 keys, but got %d\", len(objs))\n\t\t\t\t}\n\t\t\t\tif objs[0].Key() != key {","sourceCodeStart":891,"sourceCodeEnd":927,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/cmd/objbench.go#L891-L927","documentation":"In the `juicefs objbench` \"list objects\" case, after listing keys the code compares the listed object's mtime against the current time and requires it to be within a +/-30 second window. This message means the object storage backend reported a LastModified far from the time the key was just put, so the backend's object mtime is missing, stale, or skewed. It guards `ObjectStorage` implementations that must return accurate metadata.","triggerScenarios":"Running `juicefs objbench <object-storage-url>` against a backend whose list/Head result returns a zero, epoch, or heavily skewed mtime for the freshly written key \"test\"; also occurs when the client machine's clock differs from the storage service's clock by more than 30 seconds.","commonSituations":"Custom or third-party object storage implementations that hardcode mtime to zero or omit LastModified in LIST responses; NTP drift between the client and the storage node; backends returning mtime in a misparsed timezone.","solutions":["Check clock sync (NTP/chrony) between the client running objbench and the object storage service.","Fix the ObjectStorage implementation's List/Head to return the real object LastModified instead of a zero or placeholder time.","Verify the backend's list response parsing (timezone/epoch-seconds vs milliseconds) in pkg/object.","Re-run objbench on the same host as the storage to rule out network-induced clock skew."],"exampleFix":"// before: backend returns zero time on list\nfunc (s *store) List(...) { ... object.NewFile(key, 5, time.Time{}) ... }\n// after: propagate real LastModified\nfunc (s *store) List(...) { ... object.NewFile(key, 5, modTime) ... }","handlingStrategy":"validation","validationCode":"now := time.Now()\nif m, ok := obj.(interface{ Mtime() time.Time }); ok {\n    if m.Mtime().IsZero() {\n        return fmt.Errorf(\"backend returned zero mtime for %s\", obj.Key())\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep client and storage clocks NTP-synced.","When implementing ObjectStorage, always propagate real LastModified from List/Head responses.","Test custom backends with objbench before production use."],"tags":["object-storage","objbench","clock-skew","metadata"],"backgroundTag":"value-out-of-range","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}