Getandlock followed by upsert with correct CAS throw an error

I am trying to lock a document change it and update it with the correct CAS, and I always get an error.

I am testing it on CB 6.6.0 - Enterprise and PHP SDK 3.0.4

rpm -qa | grep couchbase

libcouchbase3-tools-3.0.4-1.el7.x86_64
libcouchbase3-3.0.4-1.el7.x86_64
libcouchbase-devel-3.0.4-1.el7.x86_64

Here is the php code:

$connstring = COUCHBSE_CONNSTRING;
$username = COUCHBASE_USERNAME;
$password = COUCHBASE_PASSWORD;
$bucketName = COUCHBASE_BUCKET;

$options = new \Couchbase\ClusterOptions();
$options->credentials($username, $password);
$ cluster = new \Couchbase\Cluster($connstring, $options);
$bucket = $cluster->bucket($bucketName);
$collection = $bucket->defaultCollection();

// Creating a new document for the purpose of the test
$collection->upsert("test", array("test" => "A"));

$documentLocked = $collection->getAndLock("test", 10); 

$objDoc = $documentLocked->content();
$objDoc = 2; //changing the content to something else

//Preparing to upsert the document
$opts = new \Couchbase\UpsertOptions();
$opts->cas($documentLocked->cas());

$collection->upsert("test", $objDoc, $opts);

Fatal error: Uncaught Couchbase\KeyExistsException: LCB_ERR_DOCUMENT_EXISTS (305) in /var/www/website/cb_test_upsert_locked.php on line 26
Couchbase\KeyExistsException: LCB_ERR_DOCUMENT_EXISTS (305) in /var/www/website/cb_test_upsert_locked.php on line 26
Call Stack:
0.0002 352160 1. {main}() /var/www/website/cb_test_upsert_locked.php:0
0.0865 636544 2. Couchbase\Collection->upsert() /var/www/website/tests/cb_test_upsert_locked.php:26

if I try to remove the document with the same CAS it is removing the document correctly.
I spent already a few hours trying to figure out what is happening and I would appreciate an answer

Thank you,

Hi @flaviu

The following post has answer

Thank you for the super fast answer.

What is the difference between upsert and replace? Upsert also has the option to provide the CAS, so why and when should I use upsert instead of replace?

Generally you should use replace if that’s what you’re trying to express. Long story short, the protocol we built upon (memcached) always allows a CAS value. This wasn’t there in the original memcached text protocol. So it’s true that replace() with CAS and upsert() with CAS have effectively the same meaning.

We did discuss this recently too and may clean it up. It’s there because the wire protocol lets you express this, but it probably doesn’t really make sense to encourage it when the code semantics are cleaner with a replace operation.

Thanks for the explanation