tursodatabase/turso · error · ArgumentException

The sync remote URL must not include a query string or fragm

Error message

The sync remote URL must not include a query string or fragment.

What it means

GetNormalizedRemoteUri rejects a RemoteUri that carries a query string (?key=value) or a fragment (#anchor). Sync URLs must identify only the remote database endpoint; the library builds its own request URIs and any query or fragment would corrupt them. The check runs before any network call, when the options are validated or normalized.

Source

Thrown at bindings/dotnet/src/Turso.Data/TursoSyncDatabaseOptions.cs:128

    public Uri RemoteUri { get; }
    public string? AuthToken { get; init; }
    public string ClientName { get; init; } = "turso-sync-dotnet";
    public TimeSpan? LongPollTimeout { get; init; }
    public bool BootstrapIfEmpty { get; init; } = true;
    public TursoPartialSyncOptions? PartialSync { get; init; }
    public TursoRemoteEncryptionOptions? RemoteEncryption { get; init; }
    public long? PushOperationsThreshold { get; init; }
    public long? PullBytesThreshold { get; init; }
    public bool ForceLogicalMvccPull { get; init; }
    public HttpClient? HttpClient { get; init; }
    public string? ExperimentalFeatures { get; init; }

    internal Uri GetNormalizedRemoteUri()
    {
        if (!RemoteUri.IsAbsoluteUri)
            throw new ArgumentException("The sync remote URL must be absolute.", nameof(RemoteUri));
        if (!string.IsNullOrEmpty(RemoteUri.Query) || !string.IsNullOrEmpty(RemoteUri.Fragment))
            throw new ArgumentException("The sync remote URL must not include a query string or fragment.", nameof(RemoteUri));
        if (!string.IsNullOrEmpty(RemoteUri.UserInfo))
            throw new ArgumentException("Use AuthToken instead of embedding credentials in the sync URL.", nameof(RemoteUri));
        if (string.IsNullOrEmpty(RemoteUri.Host))
            throw new ArgumentException("The sync remote URL must include a host.", nameof(RemoteUri));

        var scheme = RemoteUri.Scheme.ToLowerInvariant() switch
        {
            "turso" or "libsql" => Uri.UriSchemeHttps,
            "http" => Uri.UriSchemeHttp,
            "https" => Uri.UriSchemeHttps,
            _ => throw new ArgumentException(
                "The sync remote URL must use turso, libsql, HTTP, or HTTPS.",
                nameof(RemoteUri)),
        };
        var builder = new UriBuilder(RemoteUri)
        {
            Scheme = scheme,
            Port = RemoteUri.IsDefaultPort ? -1 : RemoteUri.Port,

View on GitHub (pinned to c1e5928725)

Solutions

  1. Strip the '?' query and '#' fragment from the remote URL before passing it as RemoteUri.
  2. Move any token that was placed in the query string into the AuthToken option instead.
  3. Recreate the Uri with only scheme, host, port, and path components (e.g. new Uri(builder.Scheme + builder.Host + builder.Path)).

Example fix

// before
var opts = new TursoSyncDatabaseOptions(path, new Uri("https://mydb.turso.io?token=abc"));
// after
var opts = new TursoSyncDatabaseOptions(path, new Uri("https://mydb.turso.io")) { AuthToken = "abc" };
Defensive patterns

Strategy: validation

Validate before calling

static void EnsureNoQueryOrFragment(Uri remoteUri)
{
    if (!remoteUri.IsAbsoluteUri) throw new ArgumentException("URL must be absolute");
    if (!string.IsNullOrEmpty(remoteUri.Query) || !string.IsNullOrEmpty(remoteUri.Fragment))
        throw new ArgumentException($"Sync URL must not contain query/fragment: {remoteUri}");
}

Type guard

static bool IsCleanSyncUrl(Uri u) => u.IsAbsoluteUri && string.IsNullOrEmpty(u.Query) && string.IsNullOrEmpty(u.Fragment) && string.IsNullOrEmpty(u.UserInfo);

Try / catch

try { var db = new TursoSyncDatabase(opts); }
catch (ArgumentException ex) when (ex.ParamName == nameof(TursoSyncDatabaseOptions.RemoteUri))
{
    // fix URL: strip query/fragment, then retry
}

Prevention

When it happens

Trigger: Constructing TursoSyncDatabaseOptions (or calling TursoSyncDatabase/configuration paths that invoke GetNormalizedRemoteUri/Validate) with a RemoteUri such as https://host/db?slug=foo or https://host/db#frag. Uri.Query or Uri.Fragment is non-empty at TursoSyncDatabaseOptions.cs:127-128.

Common situations: Pasting a Turso web-console URL that includes query parameters, appending API keys or tokens to the URL as query parameters, copying a URL with an anchor from documentation or a browser address bar, template code that appends database names as '?database=x'.

Related errors


AI-assisted analysis of tursodatabase/turso@c1e5928725 (2026-08-31). Data as JSON: /api/errors/3efa98523be6a0f7. Report an issue: GitHub.