tursodatabase/turso · error · InvalidOperationException

Remote Encryption Cipher and Remote Encryption Key must be s

Error message

Remote Encryption Cipher and Remote Encryption Key must be specified together.

What it means

Remote encryption for embedded replicas requires both a cipher and a key: the replica must know exactly how the remote database is encrypted. GetRemoteEncryption() validates this pair and throws InvalidOperationException when only one of 'Remote Encryption Cipher' or 'Remote Encryption Key' is provided, since a partial pair is always a configuration mistake.

Source

Thrown at bindings/dotnet/src/Turso.Data/TursoConnectionOptions.cs:117

        || HasOption("Sync Experimental Features");

    public bool HasPartialSyncOptions =>
        HasOption("Partial Bootstrap Prefix")
        || HasOption("Partial Bootstrap Query")
        || HasOption("Partial Sync Segment Size")
        || HasOption("Partial Sync Prefetch");

    public TursoEncryptionCipher? GetEncryptionCipher() => _builder.GetEncryptionCipher();

    public TursoRemoteEncryptionOptions? GetRemoteEncryption()
    {
        var cipher = RemoteEncryptionCipher;
        var key = RemoteEncryptionKey;
        if (string.IsNullOrWhiteSpace(cipher) && string.IsNullOrWhiteSpace(key))
            return null;
        if (string.IsNullOrWhiteSpace(cipher) || string.IsNullOrWhiteSpace(key))
        {
            throw new InvalidOperationException(
                "Remote Encryption Cipher and Remote Encryption Key must be specified together.");
        }

        return new TursoRemoteEncryptionOptions
        {
            Cipher = TursoRemoteEncryptionOptions.ParseCipher(cipher),
            Key = key,
        };
    }

    public Uri GetRemoteUri()
    {
        if (!Uri.TryCreate(DataSource, UriKind.Absolute, out var uri) || !IsRemoteScheme(uri.Scheme))
            throw new InvalidOperationException($"Data Source is not a remote Turso URL: {DataSource}");

        if (!string.IsNullOrEmpty(uri.Query) || !string.IsNullOrEmpty(uri.Fragment))
            throw new InvalidOperationException("Remote Turso URLs must not include query strings or fragments.");
        if (!string.IsNullOrEmpty(uri.UserInfo))

View on GitHub (pinned to 6c72522679)

Solutions

  1. Set both options: 'Remote Encryption Cipher=<cipher>' and 'Remote Encryption Key=<key>'.
  2. Use the same cipher name and key the remote primary was created with, otherwise the replica cannot read replicated pages.
  3. If the remote database is not encrypted, remove both options entirely — one alone is invalid.

Example fix

// before
"Data Source=https://mydb.turso.io;Replica Path=replica.db;Remote Encryption Key=secret"
// after
"Data Source=https://mydb.turso.io;Replica Path=replica.db;Remote Encryption Cipher=aes-256-cbc;Remote Encryption Key=secret"
Defensive patterns

Strategy: validation

Validate before calling

var cipher = opts["Remote Encryption Cipher"];
var key = opts["Remote Encryption Key"];
bool hasCipher = !string.IsNullOrWhiteSpace(cipher);
bool hasKey = !string.IsNullOrWhiteSpace(key);
if (hasCipher != hasKey)
    throw new ArgumentException("Remote Encryption Cipher and Remote Encryption Key must be set together.");

Type guard

static bool HasCompleteRemoteEncryption(string cipher, string key) =>
    !string.IsNullOrWhiteSpace(cipher) == !string.IsNullOrWhiteSpace(key);

Prevention

When it happens

Trigger: Building TursoConnectionOptions where exactly one of 'Remote Encryption Cipher' or 'Remote Encryption Key' is set (non-whitespace) and the other is missing or empty — evaluated whenever the connection (replica) options are resolved.

Common situations: Appending only 'Remote Encryption Key' because the cipher name was unknown; typo'd option name making one half of the pair unreadable; partially edited connection strings when rotating keys.

Related errors


AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-08-31). Data as JSON: /api/errors/bd8f3bd26fd95f8b. Report an issue: GitHub.