tursodatabase/turso · error · JsonException
Unexpected token for last_insert_rowid: {reader.TokenType}
Error message
Unexpected token for last_insert_rowid: {reader.TokenType} What it means
last_insert_rowid in a Hrana response may be serialized as either a JSON string or a number, so the client registers a custom JsonConverter that accepts both token types. If the server emits any other token (boolean, object, start-of-array), System.Text.Json raises this JsonException because the converter has no valid value to produce.
Source
Thrown at bindings/dotnet/src/Turso.Serverless.Client/HranaProtocol.cs:355
[JsonPropertyName("is_explain")]
public bool IsExplain { get; set; }
[JsonPropertyName("is_readonly")]
public bool IsReadonly { get; set; }
}
/// <summary>The server sends <c>last_insert_rowid</c> as either a JSON string or a number.</summary>
internal sealed class LongFromStringOrNumberConverter : JsonConverter<long?>
{
public override long? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return reader.TokenType switch
{
JsonTokenType.Null => null,
JsonTokenType.String => long.Parse(reader.GetString()!, CultureInfo.InvariantCulture),
JsonTokenType.Number => reader.GetInt64(),
_ => throw new JsonException($"Unexpected token for last_insert_rowid: {reader.TokenType}"),
};
}
public override void Write(Utf8JsonWriter writer, long? value, JsonSerializerOptions options)
{
if (value is null)
{
writer.WriteNullValue();
}
else
{
writer.WriteNumberValue(value.Value);
}
}
}
View on GitHub (pinned to 244cde92a7)
Solutions
- Verify options.Url points at the real Turso/libsql Hrana endpoint (libsql://... or https URL of the database)
- Log the raw response body when the exception surfaces to see which token actually arrived
- Update Turso.Serverless.Client to the latest version for broader converter coverage
- If a reverse proxy sits in front of Turso, configure it to pass JSON bodies through unmodified
Defensive patterns
Strategy: try-catch
Try / catch
try { var rs = await conn.ExecuteAsync(sql, cmd, timeout, ct); } catch (JsonException ex) when (ex.Message.Contains("last_insert_rowid")) { log.RawResponse(); throw new TursoServerlessException("Server sent an unexpected last_insert_rowid payload; check endpoint URL and versions", ex); } Prevention
- Pin the client package and server to compatible versions
- Smoke-test the endpoint with a trivial INSERT before shipping integration code
- Keep the connection URL in configuration so switching endpoints is a config change, not code
When it happens
Trigger: The response element containing last_insert_rowid arrives as true, an object, or a truncated body; typically caused by a gateway/proxy rewriting the body, a non-Hrana endpoint returning JSON in a different shape, or a version-skewed server emitting a new representation the converter does not know.
Common situations: options.Url pointing at a load balancer or edge worker that mangles responses; HTML error pages parsed as JSON during outages; mixing an old client with a newer server build that changed the field shape.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Only finite numbers (not Infinity or NaN) can be passed as a
- Extensions array cannot be null.
- Empty pipeline response
- Describe execution failed
- Unexpected describe response
AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20).
Data as JSON: /api/errors/d329b16465f77c20.
Report an issue: GitHub.