{"record":{"id":"8a07388709bb7d7f","repo":"tursodatabase/turso","slug":"unsupported-keyword-keyword","errorCode":null,"errorMessage":"Unsupported keyword: {keyword}","messagePattern":"Unsupported keyword: (.+?)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Data/TursoConnectionStringBuilder.cs","lineNumber":347,"sourceCode":"        {\n            \"aes128gcm\" => TursoEncryptionCipher.Aes128Gcm,\n            \"aes256gcm\" => TursoEncryptionCipher.Aes256Gcm,\n            \"aegis256\" => TursoEncryptionCipher.Aegis256,\n            \"aegis256x2\" => TursoEncryptionCipher.Aegis256x2,\n            \"aegis128l\" => TursoEncryptionCipher.Aegis128l,\n            \"aegis128x2\" => TursoEncryptionCipher.Aegis128x2,\n            \"aegis128x4\" => TursoEncryptionCipher.Aegis128x4,\n            _ => throw new InvalidOperationException($\"Unknown encryption cipher: {cipher}\")\n        };\n    }\n\n    private static string NormalizeKeyword(string keyword)\n    {\n        ArgumentException.ThrowIfNullOrWhiteSpace(keyword);\n        if (KeywordMap.TryGetValue(keyword, out var normalizedKeyword))\n            return normalizedKeyword;\n\n        throw new ArgumentException($\"Unsupported keyword: {keyword}\", nameof(keyword));\n    }\n\n    private string GetString(string keyword) => GetOption(keyword) ?? string.Empty;\n\n    private void SetString(string keyword, string value)\n    {\n        ArgumentNullException.ThrowIfNull(value);\n        this[keyword] = value;\n    }\n\n    private bool GetBool(string keyword, bool defaultValue = false)\n    {\n        return TryGetValue(keyword, out var value)\n            ? Convert.ToBoolean(value, CultureInfo.InvariantCulture)\n            : defaultValue;\n    }\n\n    private bool? GetNullableBool(string keyword)","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/tursodatabase/turso/blob/c1e59287258d99b309e362a63f48822256e2f65f/bindings/dotnet/src/Turso.Data/TursoConnectionStringBuilder.cs#L329-L365","documentation":"TursoConnectionStringBuilder.NormalizeKeyword() throws this ArgumentException for any connection-string keyword not in its KeywordMap. The builder is a closed keyword set: only Data Source (DataSource/Filename), Mode, Cache, Password, Foreign Keys, Recursive Triggers, Default Timeout (Command Timeout), Pooling, Vfs, Encryption Cipher, Encryption Key, Auth Token (Authentication Token), Replica Path, Read Your Writes, Sync Interval, and Tls are accepted (each with and without spaces). Unknown keys are rejected rather than ignored so typos fail fast.","triggerScenarios":"Assigning ConnectionString or the indexer with keys like 'Server=', 'Database=', 'User ID=', 'Version=', 'Journal Mode=', 'Max Pool Size=', or misspelling a valid key ('Datasource=', 'AuthTokem='). DbConnectionStringBuilder normally tolerates unknown keys, but this override validates every key through NormalizeKeyword on get, set, ContainsKey, Remove, and TryGetValue.","commonSituations":"Porting a connection string from SQL Server/Npgsql/MySQL ('Server=;Database=;User Id=;Password=' style); copying Microsoft.Data.Sqlite options that this builder never implemented ('Journal Mode', 'Busy Timeout', 'Default Timeout' exists but 'Busy Timeout' does not); CI secrets injecting extra keys into the connection string.","solutions":["Map foreign keys to the Turso equivalents: Server/Host -> Data Source, token/password -> Auth Token or Password, timeout -> Default Timeout.","Remove keys the provider does not support instead of leaving them commented-in.","Check spelling and spacing variants against the accepted list (e.g. 'Datasource' is invalid; 'DataSource' and 'Data Source' both work)."],"exampleFix":"// before\nvar cs = \"Server=db.example.com;Database=app;User Id=sa;Password=pw;Timeout=30\";\n\n// after\nvar cs = \"Data Source=libsql://db.example.com;Auth Token=pw;Default Timeout=30\";","handlingStrategy":"validation","validationCode":"var b = new TursoConnectionStringBuilder();\nforeach (var key in incomingKeys)\n    if (!b.ContainsKey(key)) // throws on unknown; use a whitelist check first instead\n        { }\n// safer: validate against your own allowed-key list before assigning ConnectionString","typeGuard":null,"tryCatchPattern":"try { builder.ConnectionString = cs; } catch (ArgumentException ex) when (ex.Message.StartsWith(\"Unsupported keyword\")) { /* extract keyword, report which key is invalid to config owner */ }","preventionTips":["Validate external connection strings in one place at startup rather than at first connection.","When porting from other providers, map keys explicitly (Server->Data Source, Password->Auth Token) instead of pasting."],"tags":["csharp","dotnet","connection-string","keyword","config-validation"],"backgroundTag":"unknown-connection-string-key","analyzedSha":"c1e59287258d99b309e362a63f48822256e2f65f","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}