tursodatabase/turso · warning · System.Text.Json.JsonException
Extensions array cannot be null.
Error message
Extensions array cannot be null.
What it means
ExtensionsJsonConverter deserializes the Platform API's Extensions union: the string "all", or an array of names. When the JSON token is an array but JsonSerializer.Deserialize<string[]> returns null, it throws JsonException with this message. A StartArray token essentially cannot produce null under normal options, so this is a defensive guard against degenerate input or interfering custom converters.
Source
Thrown at bindings/dotnet/src/Turso.Platform.Client/TursoPlatformClient.Supplement.cs:38
{
ArgumentNullException.ThrowIfNull(names);
return new Extensions(names.ToArray());
}
/// <summary>The explicitly enabled extension names, or <see langword="null"/> for <see cref="All"/>.</summary>
public IReadOnlyList<string>? Names { get; }
}
internal sealed class ExtensionsJsonConverter : System.Text.Json.Serialization.JsonConverter<Extensions>
{
public override Extensions Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
{
return reader.TokenType switch
{
System.Text.Json.JsonTokenType.String when reader.GetString() == "all" => Extensions.All,
System.Text.Json.JsonTokenType.StartArray => Extensions.FromNames(
System.Text.Json.JsonSerializer.Deserialize<string[]>(ref reader, options)
?? throw new System.Text.Json.JsonException("Extensions array cannot be null.")),
_ => throw new System.Text.Json.JsonException("Extensions must be \"all\" or an array of extension names."),
};
}
public override void Write(System.Text.Json.Utf8JsonWriter writer, Extensions value, System.Text.Json.JsonSerializerOptions options)
{
if (value.Names is null)
{
writer.WriteStringValue("all");
return;
}
System.Text.Json.JsonSerializer.Serialize(writer, value.Names, options);
}
}
View on GitHub (pinned to 244cde92a7)
Solutions
- Send well-formed payloads: "extensions": ["crypto","regexp"] or "extensions": "all"; avoid null elements.
- Build requests with the typed Extensions class (Extensions.All / Extensions.FromNames) instead of hand-writing JSON.
- Use plain JsonSerializerOptions (web defaults) when deserializing Platform DTOs so the built-in converter behavior is not overridden.
- If you wrap deserialization, validate the parsed array for null entries before proceeding.
Example fix
// before
{ "extensions": [null, "crypto"] }
// after
{ "extensions": ["crypto", "regexp"] } Defensive patterns
Strategy: validation
Validate before calling
// validate the extensions payload shape before deserializing
using var doc = JsonDocument.Parse(json);
var token = doc.RootElement.GetProperty("extensions");
bool ok = (token.ValueKind == JsonValueKind.String && token.GetString() == "all")
|| (token.ValueKind == JsonValueKind.Array && token.EnumerateArray().All(e => e.ValueKind == JsonValueKind.String)); Try / catch
try { var ext = JsonSerializer.Deserialize<Extensions>(json); }
catch (JsonException) { /* payload malformed: fix producer or reject request */ } Prevention
- Use the typed Extensions class instead of hand-built JSON.
- Use default JsonSerializerOptions for Platform DTOs; do not attach custom string[] converters.
- Never emit null entries in the extensions array.
When it happens
Trigger: Deserializing a request/response body where "extensions" is an array token that yields null — realistically only with custom JsonSerializerOptions string[] converters, malformed framing, or a hand-rolled reader pipeline; ordinary payloads like [] or ["crypto"] never take this path.
Common situations: Unit tests that share a JsonSerializerOptions instance with custom converters; intermediate middleware that rewrites bodies; virtually never seen from the real Platform API.
Related errors
- Extensions must be "all" or an array of extension names.
- Unexpected token for last_insert_rowid: {reader.TokenType}
- Unable to parse remote response: {ex.Message}
- Remote response {Type} returned an empty result.
- Unable to parse remote {Type} response: {ex.Message}
AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20).
Data as JSON: /api/errors/9ab0c17229e89388.
Report an issue: GitHub.