tursodatabase/turso · error · ArgumentException

Keyword not supported: {keyword}.

Error message

Keyword not supported: {keyword}.

What it means

ArgumentException thrown by NormalizeKeyword when the connection-string builder's indexer (get or set) receives a keyword that is not in its KeywordMap. Only a fixed set is supported: Data Source/DataSource/Filename, Mode, Cache, Password, Foreign Keys/ForeignKeys, Recursive Triggers/RecursiveTriggers, Default Timeout/DefaultTimeout/Command Timeout/CommandTimeout, Pooling, Vfs, DateTimeKind, DateTimeFormat, BinaryGUID/BinaryGuid/Binary GUID, and Version. Unknown keys that Microsoft.Data.Sqlite or System.Data.SQLite accept (Cache Size, Page Size, Journal Mode, ...) are rejected here.

Source

Thrown at bindings/dotnet/src/Turso.Data.Sqlite/SqliteConnectionStringBuilder.cs:222

    internal string GetTursoConnectionString()
    {
        var builder = new DbConnectionStringBuilder();
        if (!string.IsNullOrEmpty(DataSource))
            builder["Data Source"] = DataSource;
        if (DefaultTimeout != 30)
            builder["Default Timeout"] = DefaultTimeout;

        return builder.ConnectionString;
    }

    private static string NormalizeKeyword(string keyword)
    {
        ArgumentException.ThrowIfNullOrWhiteSpace(keyword);
        if (KeywordMap.TryGetValue(keyword, out var normalizedKeyword))
            return normalizedKeyword;

        throw new ArgumentException(Properties.Resources.KeywordNotSupported(keyword));
    }

    private string GetString(string keyword)
    {
        return base.TryGetValue(keyword, out var value)
            ? Convert.ToString(value, CultureInfo.InvariantCulture) ?? string.Empty
            : string.Empty;
    }

    private void SetString(string keyword, string? value)
    {
        if (value is null)
            Remove(keyword);
        else
            this[keyword] = value;
    }

    private bool GetBool(string keyword, bool defaultValue = false)

View on GitHub (pinned to 244cde92a7)

Solutions

  1. Remove or filter out keywords not in the supported list; keep only the 13 canonical keywords exposed by builder.Keys.
  2. Use the strongly-typed properties (builder.DataSource, builder.Mode, builder.Pooling, ...) instead of string indexer access.
  3. If you parse arbitrary user config into the builder, whitelist keys with builder.ContainsKey(keyword) (which returns false instead of throwing) before setting.

Example fix

// before
var builder = new SqliteConnectionStringBuilder("Data Source=app.db;Cache Size=2000;Page Size=4096");

// after
var builder = new SqliteConnectionStringBuilder("Data Source=app.db");
// drop unsupported tuning keywords; set supported ones via properties:
builder.Mode = SqliteOpenMode.ReadWriteCreate;
Defensive patterns

Strategy: validation

Validate before calling

foreach (var kv in rawConfig)
    if (!builder.ContainsKey(kv.Key))
        throw new ConfigException($"Unsupported connection keyword '{kv.Key}'. Allowed: {string.Join(", ", builder.Keys.Cast<string>())}");
    else
        builder[kv.Key] = kv.Value;

Try / catch

try { builder[key] = value; }
catch (ArgumentException ex) when (ex.Message.Contains("Keyword not supported"))
{ /* skip or map the keyword (e.g. drop provider-specific tuning keys) */ }

Prevention

When it happens

Trigger: builder["Cache Size"] = 2000; passing "Data Source=a.db;Journal Mode=Wal" to the SqliteConnectionStringBuilder constructor; any indexer access or property that funnels through NormalizeKeyword with an unmapped key; note plain DbConnectionStringBuilder.Clear/Remove do not throw, only keyword-addressed access does.

Common situations: Copy-pasting connection strings from Microsoft.Data.Sqlite or System.Data.SQLite samples; tuning options (page size, cache size, busy timeout) carried over during a migration; dynamically building connection strings from user/config key-value pairs without filtering keys.

Related errors


AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20). Data as JSON: /api/errors/9441aab6ef844071. Report an issue: GitHub.