{"record":{"id":"73a46688f587dfd0","repo":"juicedata/juicefs","slug":"delete-not-existed-v","errorCode":null,"errorMessage":"delete not existed: %v","messagePattern":"delete not existed: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/objbench.go","lineNumber":871,"sourceCode":"\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\n\trunCase(\"delete an object\", func(blob object.ObjectStorage) error {\n\t\tbr := []byte(\"hello\")\n\t\tif err := blob.Put(ctx, key, bytes.NewReader(br)); err != nil {\n\t\t\treturn fmt.Errorf(\"put object failed: %s\", err)\n\t\t}\n\t\tif err := blob.Delete(ctx, key); err != nil {\n\t\t\treturn fmt.Errorf(\"delete failed: %s\", err)\n\t\t}\n\t\tif _, err := blob.Head(ctx, key); err == nil {\n\t\t\treturn fmt.Errorf(\"expect err is not nil\")\n\t\t}\n\n\t\tif err := blob.Delete(ctx, key); err != nil {\n\t\t\treturn fmt.Errorf(\"delete not existed: %v\", err)\n\t\t}\n\t\treturn nil\n\t})\n\n\trunCase(\"delete non-exist\", func(blob object.ObjectStorage) error {\n\t\tif err := blob.Delete(ctx, key); err != nil {\n\t\t\treturn fmt.Errorf(\"deleting a non-existent object returns an error %v\", err)\n\t\t}\n\t\treturn nil\n\t})\n\n\trunCase(\"list objects\", func(blob object.ObjectStorage) error {\n\t\tbr := []byte(\"hello\")\n\t\tif err := blob.Put(ctx, key, bytes.NewReader(br)); err != nil {\n\t\t\treturn fmt.Errorf(\"put object failed: %s\", err)\n\t\t}\n\t\tdefer blob.Delete(ctx, key) //nolint:errcheck\n\t\tif isFileSystem {","sourceCodeStart":853,"sourceCodeEnd":889,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/cmd/objbench.go#L853-L889","documentation":"This error is raised in the 'delete an object' objbench case when deleting an ALREADY-deleted key returns an error. JuiceFS requires that Delete be idempotent: deleting a key that does not exist must succeed (be a no-op), mirroring POSIX unlink semantics. The message wraps whatever error the backend returned for the second Delete.","triggerScenarios":"The test deletes the test key, then immediately calls blob.Delete(ctx, key) again; the backend returns an error such as S3 404 NoSuchKey, Swift 404, or a filesystem ENOENT that was not mapped to nil.","commonSituations":"Implementing a custom ObjectStorage that propagates 404 from S3 instead of treating it as success; a filesystem backend returning ENOENT from os.Remove; some S3-compatible vendors (or gateways) that return errors for deleting a missing key while real S3 does not.","solutions":["In the ObjectStorage implementation, map not-found delete results to nil (treat 404/NoSuchKey/ENOENT as success) to match S3/POSIX semantics.","Check whether the target is a non-AWS S3-compatible store with stricter delete semantics; fix in the client wrapper.","Verify the vendor/SDK version — some SDKs surface delete errors that upstream S3 does not.","Add a regression test: Delete of a nonexistent key must return nil.","Rerun objbench to confirm the idempotency case passes."],"exampleFix":"// before\nfunc (s *store) Delete(ctx context.Context, key string) error {\n    _, err := s.client.DeleteObject(ctx, s.bucket, key)\n    return err // returns error when key doesn't exist\n}\n// after\nfunc (s *store) Delete(ctx context.Context, key string) error {\n    _, err := s.client.DeleteObject(ctx, s.bucket, key)\n    if isNotFound(err) {\n        return nil // deleting a missing key is a no-op\n    }\n    return err\n}","handlingStrategy":"validation","validationCode":"// guard: ensure the key was actually removed before relying on idempotent delete\nif err := blob.Delete(ctx, key); err != nil {\n    if !isNotFound(err) { return err } // treat 404 as success in your own code\n}","typeGuard":null,"tryCatchPattern":"err := blob.Delete(ctx, key)\nif err != nil && isNotFound(err) {\n    err = nil // normalize to S3/POSIX idempotent semantics\n}","preventionTips":["Implement Delete as idempotent (map 404/ENOENT to nil).","Test against the real target vendor, not just AWS S3.","Keep the JuiceFS object package and CLI versions aligned.","Add objbench to CI for custom backends."],"tags":["object-storage","delete","idempotency","benchmark"],"backgroundTag":"resource-not-found","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"}