# llUpdateKeyValue

*LSL function (requires an experience)*

```lsl
key key llUpdateKeyValue(string k, string v, integer checked, string original_value);
```

- `string k`: Key of the key-value pair to update.
- `string v`: New value for the key-value pair.
- `integer checked`: Boolean. If TRUE, requires the existing value to match original_value to complete the update; if FALSE, creates the key if needed.
- `string original_value`: String value to compare against the existing value in the datastore.

- Returns: `key`
- Energy: 10

Start an asynchronous transaction to update a key-value pair associated with the script's [Experience](/categories/experience/) with the given key (**k**) and value (**v**).

If **checked** is set to [TRUE](/constants/TRUE/) then the update will only happen if **original_value** matches the current value in key-value store, otherwise the [dataserver](/events/dataserver/) will return a failure along with the error [XP_ERROR_RETRY_UPDATE](/constants/XP_ERROR_RETRY_UPDATE/). This can be used to create an in-use flag so that [Atomicity](https://en.wikipedia.org/wiki/Atomicity_%28database_systems%29) can be achieved.

As of Jan 1, 2016 maximum bytes is 1011 for key and 4095 for value for both LSO and Mono scripts.

Using `llUpdateKeyValue` to update a key that does not exist will not generate [XP_ERROR_KEY_NOT_FOUND](/constants/XP_ERROR_KEY_NOT_FOUND/). Instead, it will generate a new key with the specified value, as if you had used [llCreateKeyValue](/functions/llCreateKeyValue/).

Returns a [key](https://wiki.secondlife.com/wiki/key) that can be used to identify the corresponding [dataserver](/events/dataserver/) event to determine if this command succeeded or failed and the results.

```lsl title="How to use" frame="terminal"
key result = llUpdateKeyValue("", "", 0, "");
```

## Caveats

- It is recommended that keys do not contain commas due to [llKeysKeyValue](/functions/llKeysKeyValue/) returning keys in CSV format.

## Examples

<details open>
<summary>Example 1</summary>

```lsl collapse={16-30}
key trans;
default
{
    state_entry()
    {
        trans = llUpdateKeyValue("FOO", "BLAH", TRUE, "BAR");
    }

    dataserver(key t, string value)
    {
        if (t == trans)
        {
            // our llUpdateKeyValue transaction is done
            list result = llCSV2List(value);
            if (llList2Integer(result, 0) == 1)
            {
                // the key-value pair was successfully updated
                llSay(0, "New key-value pair was successfully updated");
            }
            else
            {
                integer error = llList2Integer(result, 1);
                if(error == XP_ERROR_RETRY_UPDATE)
                    llSay(0, "Key-value update failed, checked value is out of date");
                else
                    llSay(0, "Key-value update failed: " + llGetExperienceErrorMessage(error) );
            }
        }
    }
}
```

</details>

<details>
<summary>This script demonstrates how to avoid update conflicts (two scripts updating the store at the same time), performing fully atomic updates is more complicated. If all scripts writing to the key-value store abide by the virtual lock ($DB_Lock), and only do updates in update_db state, then all writes will be atomic.</summary>

```lsl collapse={1-9, 21-33, 41-57, 63-86}
key tid;
list tids;

default {
    state_entry() {
        state lock_db;
    }
}

state lock_db {
    state_entry() {
        tid = llUpdateKeyValue("$DB_Lock", "LOCK", TRUE, "unlock");
    }
    dataserver(key did, string value) {
        if(did == tid) {
            string payload = llDeleteSubString(value, 0, 1);
            if(llGetSubString(value+",", 0, 1) == "1,"){
                llUpdateKeyValue("$DB_LockedBy", llDumpList2String([llGetOwner(),llGetKey(),llGetLinkKey(!!llGetLinkNumber()),llGetRegionName(),llGetPos(),llGetAttached()],":"), FALSE, "");
                state update_db;
            } else {
                integer err = (integer)payload;
                if(err == XP_ERROR_RETRY_UPDATE) {
                    llSay(0, "Database is already locked!");
                } else {
                    llSay(0, "Key-value update failed: " + llGetExperienceErrorMessage(err) );
                }
                state error;
            }
        }
    }
}

state update_db {
    state_entry() {
        tids = [
            llUpdateKeyValue("CatsPermissable", "5", FALSE, ""),
            llUpdateKeyValue("MonkeyMutations", "3", FALSE, ""),
            llUpdateKeyValue("CodFlavorSupport", "NEVER", FALSE, "")
        ];
    }
    dataserver(key did, string value) {
        integer i = llListFindList(tid, [did]);
        if(~i) {
            string payload = llDeleteSubString(value, 0, 1);
            if(llGetSubString(value+",", 0, 1) == "1,"){
                tids = llDeleteSubList(tids, i, i);
                if(tids == []) {
                    state unlock_db;
                }
            } else {
                llSay(0, "Key-value update failed: " + llGetExperienceErrorMessage((integer)payload) );
                state error;
            }
        }
    }
}

state unlock_db {
    state_entry() {
        tid = llUpdateKeyValue("$DB_Lock", "unlock", TRUE, "LOCK");
    }
    dataserver(key did, string value) {
        if(did == tid) {
            string payload = llDeleteSubString(value, 0, 1);
            if(llGetSubString(value+",", 0, 1) == "1,"){
                state done;
            } else {
                integer err = (integer)payload;
                if(err == XP_ERROR_RETRY_UPDATE) {
                    llSay(0, "Someone has violated the database lock!");
                } else {
                    llSay(0, "Key-value update failed: " + llGetExperienceErrorMessage(err) );
                }
                state error;
            }
        }
    }
}

state done {
    state_entry(){;}
}

state error {
    state_entry(){;}
}
```

</details>

## See also

### Functions

- [llGetExperienceErrorMessage](/functions/llGetExperienceErrorMessage/)
- [llCreateKeyValue](/functions/llCreateKeyValue/)
- [llReadKeyValue](/functions/llReadKeyValue/)
- [llUpdateKeyValue](/functions/llUpdateKeyValue/)
- [llDeleteKeyValue](/functions/llDeleteKeyValue/)
- [llDataSizeKeyValue](/functions/llDataSizeKeyValue/)
- [llKeyCountKeyValue](/functions/llKeyCountKeyValue/)
- [llKeysKeyValue](/functions/llKeysKeyValue/)

---

*Source: [LlUpdateKeyValue](https://wiki.secondlife.com/wiki/LlUpdateKeyValue) on the Second Life Wiki. Content from the Second Life Wiki articles LlUpdateKeyValue (revision 1209089, 2020-01-27), Template:LSL Function/KeyValue (revision 1218517, 2025-11-17) and Template:LSL Function/Experience (revision 1210521, 2022-03-11), CC BY-SA 3.0.*

---

From lsl.dev: https://lsl.dev/functions/llUpdateKeyValue/
