# Experience Data

> lsl.dev (unofficial LSL docs). Full API: https://lsl.dev/api.json · Index for LLMs: https://lsl.dev/llms.txt

> Experience persistent storage: a grid-wide key-value store shared by every script in an experience, answered through dataserver.

Scripts compiled to an [experience](/features/experience/) share a key-value store that any object in that experience can use, in any region. It suits data shared between objects, such as scores, player records or game state. Part of the [Data Storage](/features/data-storage/) feature.

## Concepts

- The store belongs to the script's experience, not to an object; a script outside an experience gets an error
- Keys are up to 1011 bytes and values up to 4095 bytes
  - Avoid commas in keys, since [`llKeysKeyValue`](/functions/llKeysKeyValue/) returns them as CSV
- Every call is asynchronous: it returns a request key, and the result arrives in [`dataserver`](/events/dataserver/)
  - The data starts with `1` on success, followed by a comma and the result
  - It starts with `0` on failure, followed by a comma and an [`XP_ERROR_*`](/constants/groups/ExperienceError/) code
- [Create](/functions/llCreateKeyValue/) fails if the key exists; [read](/functions/llReadKeyValue/) fails with [`XP_ERROR_KEY_NOT_FOUND`](/constants/XP_ERROR_KEY_NOT_FOUND/) if it does not
- [Update](/functions/llUpdateKeyValue/) writes a value, creating the key if needed
  - With **checked** set, it only writes if the current value equals **original_value**, else fails with [`XP_ERROR_RETRY_UPDATE`](/constants/XP_ERROR_RETRY_UPDATE/); this makes safe read-modify-write possible
- [Delete](/functions/llDeleteKeyValue/) removes a key
- [List keys](/functions/llKeysKeyValue/) a page at a time, [count them](/functions/llKeyCountKeyValue/), or read [used and total data](/functions/llDataSizeKeyValue/)

## Functions and events

- `key` [`llCreateKeyValue`](/functions/llCreateKeyValue/) `(string k, string v)`
- `key` [`llReadKeyValue`](/functions/llReadKeyValue/) `(string k)`
- `key` [`llUpdateKeyValue`](/functions/llUpdateKeyValue/) `(string k, string v, integer checked, string original_value)`
- `key` [`llDeleteKeyValue`](/functions/llDeleteKeyValue/) `(string k)`
- `event` [`dataserver`](/events/dataserver/) `(key queryid, string data)`

## Scripting Details

- `key` [`llCreateKeyValue`](/functions/llCreateKeyValue/) `(string k, string v)`: Starts an asynchronous transaction to create a key-value pair (k and v) associated with the script's experience. Returns a key query handle for the dataserver event. Fails with XP_ERROR_STORAGE_EXCEPTION if the key already exists.
- `key` [`llReadKeyValue`](/functions/llReadKeyValue/) `(string k)`: Starts an asynchronous transaction to read the value associated with key k in the experience. Returns a key query handle for the dataserver event. Fails with XP_ERROR_KEY_NOT_FOUND if the key does not exist.
- `key` [`llUpdateKeyValue`](/functions/llUpdateKeyValue/) `(string k, string v, integer checked, string original_value)`: Starts an asynchronous transaction to update the key k to value v inside the experience datastore. If checked is TRUE, the update fails with XP_ERROR_RETRY_UPDATE unless the existing value matches original_value.
- `key` [`llDeleteKeyValue`](/functions/llDeleteKeyValue/) `(string k)`: Starts an asynchronous transaction to delete the key-value pair associated with key k in the experience. Returns a key query handle for the dataserver event.
- `key` [`llKeysKeyValue`](/functions/llKeysKeyValue/) `(integer first, integer count)`: Starts an asynchronous transaction to retrieve count keys from the experience data store starting at the zero-based index first. Returns a key query handle for the dataserver event. Fails with XP_ERROR_KEY_NOT_FOUND if out of bounds.
- `key` [`llKeyCountKeyValue`](/functions/llKeyCountKeyValue/) `()`: Starts an asynchronous transaction requesting the total count of keys in the experience data store. Returns a key query handle for the dataserver event.
- `key` [`llDataSizeKeyValue`](/functions/llDataSizeKeyValue/) `()`: Starts an asynchronous transaction to request the used and total data storage allocated for the experience. Returns a key query handle for the dataserver event.
- `string` [`llGetExperienceErrorMessage`](/functions/llGetExperienceErrorMessage/) `(integer error)`: Returns a text description of the specified experience error code, or a description of XP_ERROR_UNKNOWN_ERROR if the error is invalid.
- `event` [`dataserver`](/events/dataserver/) `(key queryid, string data)`: Triggered when requested data is returned to the script (e.g., from llRequestAgentData, llRequestInventoryData, or llGetNotecardLine).

## Example

```lsl
key request;

default
{
    touch_start(integer num_detected)
    {
        request = llReadKeyValue("highscore");
    }

    dataserver(key id, string data)
    {
        if (id != request) return;
        if (llGetSubString(data, 0, 0) == "1")
            llSay(0, "High score: " + llGetSubString(data, 2, -1));
        else
            llSay(0, "Error: " + llGetExperienceErrorMessage((integer)llGetSubString(data, 2, -1)));
    }
}
```

## Constant groups

Constant groups: [ExperienceError](/constants/groups/ExperienceError/) (19)

## Related

See also: [Data Storage](/features/data-storage/), [Experience](/features/experience/), [Experience Data](/categories/experience_data/), [Dataserver](/categories/dataserver/)

## Related features

- [Data Storage](/features/data-storage/)
- [Experience](/features/experience/)

## Categories

- [Dataserver](/categories/dataserver/)

---

From lsl.dev: https://lsl.dev/features/data-storage/experience-data/
