git-ecosystem/git-credential-manager · error · ArgumentException

Not a valid URI

Error message

Not a valid URI: '{url}'

What it means

The SessionManagerExtensions.OpenBrowser(string) overload parses the URL with Uri.TryCreate(UriKind.Absolute) and throws ArgumentException if the string is not an absolute URI, before handing it to the underlying session manager. It guards against launching a browser with a malformed or relative URL.

Solutions

  1. Ensure the URL string includes an absolute scheme, e.g. prefix with "https://" if missing
  2. Validate the URL with Uri.TryCreate(url, UriKind.Absolute, out _) before calling OpenBrowser
  3. Check where the URL originates (config, server response) — fix the producer sending a malformed/empty URL
  4. Use UriBuilder to construct the URL from host/path components instead of string concatenation

Example fix

// before
sm.OpenBrowser($"{host}/login/device"); // host lacks scheme -> throws
// after
var url = $"https://{host}/login/device";
if (Uri.TryCreate(url, UriKind.Absolute, out var _))
    sm.OpenBrowser(url);
Defensive patterns

Strategy: validation

Validate before calling

if (!Uri.TryCreate(url, UriKind.Absolute, out var uri) ||
    (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps))
    throw new ArgumentException($"Browser URL must be an absolute http(s) URI, got: '{url}'");

Type guard

bool IsAbsoluteHttpUrl(string s) => Uri.TryCreate(s, UriKind.Absolute, out var u) &&
    (u.Scheme == Uri.UriSchemeHttp || u.Scheme == Uri.UriSchemeHttps);

Try / catch

try
{
    sm.OpenBrowser(url);
}
catch (ArgumentException ex) when (ex.Message.StartsWith("Not a valid URI"))
{
    logger.LogError(ex, "Malformed browser URL: {Url}", url);
}

Prevention

When it happens

Trigger: Calling sm.OpenBrowser(url) with a string that is not an absolute URI — empty string, relative path like "/login", missing scheme like "example.com/auth", or a URL with invalid characters.

Common situations: Building OAuth/browser authentication URLs with string concatenation that omits the https:// scheme, capturing a truncated URL from logs, or passing a null/empty value from configuration.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of git-ecosystem/git-credential-manager@e8ce762cd0 (2026-09-11). Data as JSON: /api/errors/39019c1d8aa04f2f. Report an issue: GitHub.

Appendix: source

Thrown at src/Core/ISessionManager.cs:34

        /// </summary>
        /// <returns>True if the session can display a web browser, false otherwise.</returns>
        bool IsWebBrowserAvailable { get; }

        /// <summary>
        /// Open the system web browser to the specified URL.
        /// </summary>
        /// <param name="uri"><see cref="Uri"/> to open the browser at.</param>
        /// <exception cref="InvalidOperationException">Thrown if <see cref="IsWebBrowserAvailable"/> is false.</exception>
        void OpenBrowser(Uri uri);
    }

    public static class SessionManagerExtensions
    {
        public static void OpenBrowser(this ISessionManager sm, string url)
        {
            if (!Uri.TryCreate(url, UriKind.Absolute, out Uri uri))
            {
                throw new ArgumentException($"Not a valid URI: '{url}'");
            }

            sm.OpenBrowser(uri);
        }
    }
    
    public abstract class SessionManager : ISessionManager
    {
        protected ITrace Trace { get; }
        protected IEnvironment Environment { get; }
        protected IFileSystem FileSystem { get; }

        protected SessionManager(ITrace trace, IEnvironment env, IFileSystem fs)
        {
            EnsureArgument.NotNull(trace, nameof(trace));
            EnsureArgument.NotNull(env, nameof(env));
            EnsureArgument.NotNull(fs, nameof(fs));

View on GitHub (pinned to e8ce762cd0)