tursodatabase/turso · error · TursoException
Remote request failed with HTTP {(int)response.StatusCode} {
Error message
Remote request failed with HTTP {(int)response.StatusCode} {response.ReasonPhrase}: {body} What it means
TursoRemoteClient.SendAsync wraps every non-success HTTP response in a TursoException that includes the status code, reason phrase, and the full response body. This is the single funnel for all remote-side failures: authentication problems (401/403), unknown database URLs (404), rate limiting (429), and server errors (5xx). Reading the numeric code out of the message is the way to branch on the failure class.
Source
Thrown at bindings/dotnet/src/Turso.Data/TursoRemoteClient.cs:156
var json = JsonSerializer.Serialize(request, JsonOptions);
using var content = new StringContent(json, Encoding.UTF8, "application/json");
using var httpRequest = new HttpRequestMessage(HttpMethod.Post, _pipelineUri)
{
Content = content,
};
if (_authToken is not null)
httpRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _authToken);
using var response = await _httpClient
.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead, effectiveCancellationToken)
.ConfigureAwait(false);
var body = await response.Content.ReadAsStringAsync(effectiveCancellationToken).ConfigureAwait(false);
if (!response.IsSuccessStatusCode)
{
throw new TursoException(
$"Remote request failed with HTTP {(int)response.StatusCode} {response.ReasonPhrase}: {body}");
}
try
{
return JsonSerializer.Deserialize<RemotePipelineResponse>(body, JsonOptions)
?? throw new TursoException("Remote request returned an empty response.");
}
catch (JsonException ex)
{
throw new TursoException($"Unable to parse remote response: {ex.Message}");
}
}
private static CancellationTokenSource? CreateTimeout(int commandTimeout, CancellationToken cancellationToken)
{
if (commandTimeout <= 0)
return null;View on GitHub (pinned to 6c72522679)
Solutions
- For 401/403: verify the Auth Token is valid and scoped to the database in the Data Source URL (re-issue with the Turso CLI).
- For 404: check the Data Source host matches the database URL shown in the Turso dashboard (watch for typos and stale URLs).
- For 429/5xx: retry with exponential backoff and jitter; these classes are transient.
- For proxy interference: ensure egress to *.turso.io is direct and the Authorization header survives.
Example fix
// before
var results = await client.ExecuteBatchAsync(batch, 30, true, false, ct);
// after
catch (TursoException ex) when (ex.Message.StartsWith("Remote request failed with HTTP 4"))
{
// non-retryable: token/URL/config problem — surface it
logger.LogError(ex, "Remote Turso call rejected");
throw;
} Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight sanity (cheap, catches most 401/404 before first query):
if (string.IsNullOrWhiteSpace(options.AuthToken)) throw new ConfigurationException("Turso Auth Token missing");
if (!options.IsRemote) throw new ConfigurationException("Data Source must be a remote URL"); Type guard
static int? ExtractHttpStatus(TursoException ex)
{
const string prefix = "Remote request failed with HTTP ";
return ex.Message.StartsWith(prefix) && int.TryParse(ex.Message.AsSpan(prefix.Length, 3), out var code)
? code : null;
} Try / catch
catch (TursoException ex) when (ExtractHttpStatus(ex) is 408 or 429 or >= 500)
{
await Task.Delay(backoff.Next(), ct); // exponential backoff + jitter, then retry
}
catch (TursoException ex) when (ExtractHttpStatus(ex) is 401 or 403)
{
logger.LogError(ex, "Turso auth failed — refresh the database token");
throw;
} Prevention
- Refresh short-lived database tokens on a schedule before expiry, not on failure.
- Wrap remote calls in retry-with-backoff for 429/5xx only; never retry 4xx auth/config errors.
- Log the status code (parsed from the message) plus request ID so support tickets are actionable.
When it happens
Trigger: Any remote pipeline request where the server returns non-2xx: an expired or wrong Auth Token (401), a token without access to the database (403), a Data Source URL pointing at a nonexistent database (404), plan limits or burst traffic (429), or Turso Cloud incidents (5xx). Also seen when a proxy or captive portal answers with an unexpected status and HTML body.
Common situations: Rotated/short-lived database tokens not refreshed in long-running services; wrong database URL copied between projects; CI hitting rate limits during parallel test runs; corporate proxies intercepting requests; scheduled token expiry caught only in production.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Batch must contain at least one command.
- Remote Turso URLs must not include query strings or fragment
- Embedded replica sync is not supported yet by the .NET provi
- Embedded replica connections are not supported yet by the .N
- Sync Interval requires embedded replica support, which is no
AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-08-20).
Data as JSON: /api/errors/5aaf2be65b01feb9.
Report an issue: GitHub.