> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lancedb.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Secret

> Create, rotate, list, describe and drop a named credential that Functions bind by reference.

**Applies to:** Embedded ❌, Enterprise ✅

Early access

A **Secret** is a catalog object, like a table or a namespace: a named
credential, such as a model provider's API key, stored once and addressed by
name. A [Function](https://docs.lancedb.com/curation/create-function.md) binds a Secret by reference
when you register it, never by value; see
[Vend a Secret to a Function](https://docs.lancedb.com/curation/vend-secret.md) for how that binding
reaches running code.

The design rule is **bind by reference, resolve late**. A Function records
*which* Secret it reads, never the value, and the value is looked up each
time a job starts. That is what lets a credential be rotated or revoked
without touching the Functions, columns or tables that use it.

## Create and manage

Every call takes an optional `namespace_path`; the default is the root
namespace.

```python Python theme={"theme":{"light":"vitesse-light","dark":"catppuccin-mocha"}}
db.create_secret("openai-prod", value, namespace_path=["platform"])

db.alter_secret("openai-prod", new_value, namespace_path=["platform"])

for name in db.list_secrets(namespace_path=["platform"]):
    print(name)

info = db.describe_secret("openai-prod", namespace_path=["platform"])
info.created_at_millis, info.updated_at_millis

db.drop_secret("openai-prod", namespace_path=["platform"])
```

```sql SQL theme={"theme":{"light":"vitesse-light","dark":"catppuccin-mocha"}}
CREATE SECRET platform.`openai-prod` TYPE = GENERIC_STRING SECRET_STRING = 'sk-...';

ALTER SECRET platform.`openai-prod` SET SECRET_STRING = 'sk-...';

SHOW SECRETS IN platform;

DESCRIBE SECRET platform.`openai-prod`;

DROP SECRET platform.`openai-prod`;
```

```rust theme={"theme":{"light":"vitesse-light","dark":"catppuccin-mocha"}}
use futures::TryStreamExt;

let namespace = vec!["platform".to_string()];

db.create_secret("openai-prod", &value, &namespace).await?;

db.alter_secret("openai-prod", &new_value, &namespace).await?;

let mut names = db.list_secrets(&namespace, Default::default());
while let Some(name) = names.try_next().await? {
    println!("{name}");
}

let info = db.describe_secret("openai-prod", &namespace).await?;
println!("{} {}", info.created_at_millis, info.updated_at_millis);

db.drop_secret("openai-prod", &namespace).await?;
```

A Secret's value is never returned by any interface: `create` and
`alter` take it as input and return nothing, and `describe` reports only
metadata. Python and Rust both expose the full lifecycle shown above;
TypeScript does not yet, and is tracked separately. See the
[SQL reference](https://docs.lancedb.com/sql/ddl/secret.md) for the same operations' SQL syntax and
result rows.

> [!NOTE]
>
> SQL has no syntax for binding a Secret to a Function. Register Functions that
> bind Secrets through the Python SDK; see
> [Vend a Secret to a Function](https://docs.lancedb.com/curation/vend-secret.md).

## Properties and guarantees

LanceDB guarantees that:

* No API returns a Secret's value.
* Values do not appear in Function source, Function versions, jobs, logs, or
  error messages. Errors raised by Function code are redacted, within
  [limits](#redaction).
* A Function receives only the Secrets bound to it.
* Values are always [encrypted at rest](#encryption).

Redaction is a safety net, not a boundary: Function code that logs, returns
or sends a credential will leak it.

### Encryption at rest

Every Secret's value is encrypted directly with your deployment's key in AWS
KMS, Google Cloud KMS, or Azure Key Vault -- there is no separate application
data key to manage. Storage, backups and replicas hold only ciphertext.
Decryption goes through your KMS, which records it in your cloud's audit
log.

BYOC You are responsible for the network egress
policy for the jobs that run Functions.

### Redaction

If a Function raises an error or skips a row with a message that contains a
bound value, LanceDB replaces each exact occurrence with `[REDACTED]` before
the message is recorded. Redaction matches only the exact value: a value
that is base64-encoded, sliced, or otherwise transformed is not caught.
Function code that prints a credential, writes it into a column, or sends
it elsewhere will leak it, so review a Function bound to a Secret as code
that holds that credential.

## Limits

| Item | Limit |
| - | - |
| Secret name | 1--128 characters from `A-Z a-z 0-9 _ . -`. `$` is reserved as the namespace delimiter. |
| Value | One nonempty UTF-8 string, at most 4,096 bytes. On Azure, at most 158, 286 or 414 bytes for an RSA-2048, RSA-3072 or RSA-4096 key. |
| Bindings per Function | 16 |
| Environment variable name | `[A-Za-z_][A-Za-z0-9_]*`, and not [reserved](#reserved) |
| Variables per Function | Each bound once. Two variables may bind the same Secret. |
| `describe` history | The most recent 100 alterations |

### Reserved variables

A Secret cannot be bound to a variable that LanceDB sets for Functions
itself. These names are reserved:

* Exact names: `HOME`, `PATH`, `TEMP`, `TMP`, `TMPDIR`, `LANG`, `LC_ALL`,
  `LC_CTYPE`, `TZ`, `HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY` (and their
  lowercase forms), `SSL_CERT_FILE`, `SSL_CERT_DIR`, `REQUESTS_CA_BUNDLE`,
  `UV_CACHE_DIR`, `UV_NATIVE_TLS`, `UV_PYTHON_INSTALL_DIR`, `RUST_BACKTRACE`
* Prefixes: `DYLD_`, `LANCE_`, `LANCEDB_`, `LD_`, `PYTHON`, and a few others
  LanceDB reserves for its own use. `create_function` refuses a reserved
  name and says which one.

## Troubleshooting

**`Secret 'X', bound to VAR, does not exist`** when adding a column or
refreshing one: the Secret was never created in that namespace, was dropped,
or its name is misspelled in the binding. Create it, or register a new
Function version with the right name.

**501 from a Secret API call**: Secrets aren't enabled for this deployment.
Contact [LanceDB support](https://docs.lancedb.com/deployment/support.md).

## Privileges

A Secret is its own object in the authorization model, a namespace child
like a table, so a grant names one credential rather than a whole
database. See [Privileges](https://docs.lancedb.com/governance/privileges.md#secret-operations) for
the privilege each operation above requires, and
[GRANT and REVOKE](https://docs.lancedb.com/sql/ddl/secret.md#grant) for the full SQL statement
syntax.

## What to read next

> [card] [Vend a Secret to a Function](https://docs.lancedb.com/curation/vend-secret.md)
>
> Bind a Secret when you register a Function, and how rotation reaches
> code that is already running.

> [card] [Privileges](https://docs.lancedb.com/governance/privileges.md#sql)
>
> Grant and revoke privileges on a Secret.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.