diff --git a/bucket.go b/bucket.go index 0c5bf2746..93f9d9515 100644 --- a/bucket.go +++ b/bucket.go @@ -323,7 +323,12 @@ func (b *Bucket) Delete(key []byte) error { // Move cursor to correct position. c := b.Cursor() - _, _, flags := c.seek(key) + k, _, flags := c.seek(key) + + // Return nil if the key doesn't exist. + if !bytes.Equal(key, k) { + return nil + } // Return an error if there is already existing bucket value. if (flags & bucketLeafFlag) != 0 { diff --git a/bucket_test.go b/bucket_test.go index c75f71fff..6d96e662f 100644 --- a/bucket_test.go +++ b/bucket_test.go @@ -441,6 +441,39 @@ func TestBucket_Delete_FreelistOverflow(t *testing.T) { } } +// Ensure that deleting of non-existing key is a no-op. +func TestBucket_Delete_NonExisting(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if _, err = b.CreateBucket([]byte("nested")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + if err := b.Delete([]byte("foo")); err != nil { + t.Fatal(err) + } + if b.Bucket([]byte("nested")) == nil { + t.Fatal("nested bucket has been deleted") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + // Ensure that accessing and updating nested buckets is ok across transactions. func TestBucket_Nested(t *testing.T) { db := MustOpenDB()