{"record":{"id":"112d68d108d0be18","repo":"tursodatabase/turso","slug":"extensions-must-be-all-or-an-array-of-extension","errorCode":null,"errorMessage":"Extensions must be \"all\" or an array of extension names.","messagePattern":"Extensions must be \"all\" or an array of extension names\\.","errorType":"validation","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Platform.Client/TursoPlatformClient.Supplement.cs","lineNumber":39,"sourceCode":"        ArgumentNullException.ThrowIfNull(names);\n        return new Extensions(names.ToArray());\n    }\n\n    /// <summary>The explicitly enabled extension names, or <see langword=\"null\"/> for <see cref=\"All\"/>.</summary>\n    public IReadOnlyList<string>? Names { get; }\n}\n\ninternal sealed class ExtensionsJsonConverter : System.Text.Json.Serialization.JsonConverter<Extensions>\n{\n    public override Extensions Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options)\n    {\n        return reader.TokenType switch\n        {\n            System.Text.Json.JsonTokenType.String when reader.GetString() == \"all\" => Extensions.All,\n            System.Text.Json.JsonTokenType.StartArray => Extensions.FromNames(\n                System.Text.Json.JsonSerializer.Deserialize<string[]>(ref reader, options)\n                ?? throw new System.Text.Json.JsonException(\"Extensions array cannot be null.\")),\n            _ => throw new System.Text.Json.JsonException(\"Extensions must be \\\"all\\\" or an array of extension names.\"),\n        };\n    }\n\n    public override void Write(System.Text.Json.Utf8JsonWriter writer, Extensions value, System.Text.Json.JsonSerializerOptions options)\n    {\n        if (value.Names is null)\n        {\n            writer.WriteStringValue(\"all\");\n            return;\n        }\n\n        System.Text.Json.JsonSerializer.Serialize(writer, value.Names, options);\n    }\n}\n","sourceCodeStart":21,"sourceCodeEnd":54,"githubUrl":"https://github.com/tursodatabase/turso/blob/244cde92a7df7f9b8b8b7a4075c35a12977e303e/bindings/dotnet/src/Turso.Platform.Client/TursoPlatformClient.Supplement.cs#L21-L54","documentation":"The Extensions union deserializes from exactly two shapes: the string \"all\" or an array of extension names. Any other JSON token for the \"extensions\" property — boolean, number, object, or a string other than \"all\" (e.g. \"crypto\", \"crypto,regexp\") — throws JsonException with this message during deserialization.","triggerScenarios":"POSTing a group-create/update payload with \"extensions\": true, \"extensions\": \"crypto\", or \"extensions\": {\"names\":[...]}; any wrapper that flattens the union to a flag or comma-separated string instead of the two supported shapes.","commonSituations":"Hand-crafted REST calls or integrations built against older API shapes; wrappers exposing a bool enableExtensions that serializes directly; copy-pasting example payloads that predate the union type.","solutions":["Fix the payload: \"extensions\": \"all\" or \"extensions\": [\"crypto\", \"regexp\"].","Use the Extensions class (Extensions.All, Extensions.FromNames(...)) and let its converter serialize correctly.","If you expose your own config surface, map booleans to the union (true -> \"all\", false -> omit) before sending.","Validate outgoing bodies against the Platform API schema in CI to catch shape regressions."],"exampleFix":"// before\n{ \"extensions\": true }\n\n// after\n{ \"extensions\": \"all\" }\n// or\n{ \"extensions\": [\"crypto\", \"regexp\"] }","handlingStrategy":"validation","validationCode":"// accept only the two legal shapes before sending\nstatic bool IsValidExtensions(JsonElement e) =>\n    (e.ValueKind == JsonValueKind.String && e.GetString() == \"all\")\n    || (e.ValueKind == JsonValueKind.Array && e.EnumerateArray().All(x => x.ValueKind == JsonValueKind.String));","typeGuard":"static bool IsExtensionsPayload(object o) => o is Extensions;","tryCatchPattern":"try { await client.CreateGroupAsync(payload); }\ncatch (JsonException ex) when (ex.Message.Contains(\"extensions\")) { /* normalize the field to \\\"all\\\" or a name array and retry */ }","preventionTips":["Map booleans/flags to the union shape (true -> \"all\", false -> omit) at your config boundary.","Contract-test outgoing payloads against the Platform API schema.","Let the Extensions converter serialize; never serialize a raw string/bool into that field."],"tags":["dotnet","json","platform-api","payload-validation"],"backgroundTag":"json-schema-validation","analyzedSha":"244cde92a7df7f9b8b8b7a4075c35a12977e303e","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}