dotnetcore/CAP · error · ArgumentNullException

Value cannot be null. (Parameter 'scheme')

Error message

Value cannot be null. (Parameter 'scheme')

What it means

GetEncodedUrl/BuildAbsolute in IRequestMapper.Default validates the scheme parameter and throws ArgumentNullException when HttpContext.Request.Scheme is null. It cannot compose an absolute URL without a scheme. This typically happens when the Dashboard is accessed in an environment that never sets Request.Scheme.

Solutions

  1. Configure app.UseForwardedHeaders (X-Forwarded-Proto) so Scheme is populated behind a proxy.
  2. Set the scheme explicitly at the call site: BuildAbsolute(request.Scheme ?? "http", ...).
  3. If the dashboard node URL is known, bypass scheme inference and build the URL from configured options.
  4. Validate scheme before calling and surface a clearer error.

Example fix

// before
var url = UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase, request.Path, request.QueryString);
// after
var url = UriHelper.BuildAbsolute(request.Scheme ?? "http", request.Host, request.PathBase, request.Path, request.QueryString);
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrEmpty(request.Scheme))
    request.Scheme = "http"; // or derive from X-Forwarded-Proto
var url = UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase, request.Path, request.QueryString);

Try / catch

try { BuildAbsolute(scheme, ...); }
catch (ArgumentNullException) when (((ArgumentNullException)ex).ParamName == "scheme") { /* fall back to configured scheme */ }

Prevention

When it happens

Trigger: Mapping an incoming Dashboard request whose HttpRequest.Scheme is null (or explicitly calling BuildAbsolute(null, ...)) while constructing the absolute URL for the proxied node request.

Common situations: Hosting behind a reverse proxy without UseForwardedHeaders, in-process/test servers that omit scheme, or custom middleware that resets Request features.

Related errors


AI-assisted analysis of dotnetcore/CAP@e52b8508e5 (2026-09-14). Data as JSON: /api/errors/5cb800dc7f6cd464. Report an issue: GitHub.

Appendix: source

Thrown at src/DotNetCore.CAP.Dashboard/GatewayProxy/IRequestMapper.Default.cs:50

            MapHeaders(request, requestMessage);

            return requestMessage;
        }
        catch (Exception ex)
        {
            throw new Exception($"Error when parsing incoming request, exception: {ex.Message}");
        }
    }

    private string BuildAbsolute(
        string scheme,
        HostString host,
        PathString pathBase = new(),
        PathString path = new(),
        QueryString query = new(),
        FragmentString fragment = new())
    {
        if (scheme == null) throw new ArgumentNullException(nameof(scheme));

        var combinedPath = pathBase.HasValue || path.HasValue ? (pathBase + path).ToString() : "/";

        var encodedHost = host.ToString();
        var encodedQuery = query.ToString();
        var encodedFragment = fragment.ToString();

        // PERF: Calculate string length to allocate correct buffer size for StringBuilder.
        var length = scheme.Length + SchemeDelimiter.Length + encodedHost.Length
                     + combinedPath.Length + encodedQuery.Length + encodedFragment.Length;

        return new StringBuilder(length)
            .Append(scheme)
            .Append(SchemeDelimiter)
            .Append(encodedHost)
            .Append(combinedPath)
            .Append(encodedQuery)
            .Append(encodedFragment)

View on GitHub (pinned to e52b8508e5)