{"record":{"id":"5cb800dc7f6cd464","repo":"dotnetcore/CAP","slug":"value-cannot-be-null-parameter-scheme","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'scheme')","messagePattern":"Value cannot be null\\. \\(Parameter 'scheme'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/DotNetCore.CAP.Dashboard/GatewayProxy/IRequestMapper.Default.cs","lineNumber":50,"sourceCode":"            MapHeaders(request, requestMessage);\n\n            return requestMessage;\n        }\n        catch (Exception ex)\n        {\n            throw new Exception($\"Error when parsing incoming request, exception: {ex.Message}\");\n        }\n    }\n\n    private string BuildAbsolute(\n        string scheme,\n        HostString host,\n        PathString pathBase = new(),\n        PathString path = new(),\n        QueryString query = new(),\n        FragmentString fragment = new())\n    {\n        if (scheme == null) throw new ArgumentNullException(nameof(scheme));\n\n        var combinedPath = pathBase.HasValue || path.HasValue ? (pathBase + path).ToString() : \"/\";\n\n        var encodedHost = host.ToString();\n        var encodedQuery = query.ToString();\n        var encodedFragment = fragment.ToString();\n\n        // PERF: Calculate string length to allocate correct buffer size for StringBuilder.\n        var length = scheme.Length + SchemeDelimiter.Length + encodedHost.Length\n                     + combinedPath.Length + encodedQuery.Length + encodedFragment.Length;\n\n        return new StringBuilder(length)\n            .Append(scheme)\n            .Append(SchemeDelimiter)\n            .Append(encodedHost)\n            .Append(combinedPath)\n            .Append(encodedQuery)\n            .Append(encodedFragment)","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/dotnetcore/CAP/blob/e52b8508e54cdb7a9ce7f9fec03d9ea8ad2710fb/src/DotNetCore.CAP.Dashboard/GatewayProxy/IRequestMapper.Default.cs#L32-L68","documentation":"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.","triggerScenarios":"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.","commonSituations":"Hosting behind a reverse proxy without UseForwardedHeaders, in-process/test servers that omit scheme, or custom middleware that resets Request features.","solutions":["Configure app.UseForwardedHeaders (X-Forwarded-Proto) so Scheme is populated behind a proxy.","Set the scheme explicitly at the call site: BuildAbsolute(request.Scheme ?? \"http\", ...).","If the dashboard node URL is known, bypass scheme inference and build the URL from configured options.","Validate scheme before calling and surface a clearer error."],"exampleFix":"// before\nvar url = UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase, request.Path, request.QueryString);\n// after\nvar url = UriHelper.BuildAbsolute(request.Scheme ?? \"http\", request.Host, request.PathBase, request.Path, request.QueryString);","handlingStrategy":"validation","validationCode":"if (string.IsNullOrEmpty(request.Scheme))\n    request.Scheme = \"http\"; // or derive from X-Forwarded-Proto\nvar url = UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase, request.Path, request.QueryString);","typeGuard":null,"tryCatchPattern":"try { BuildAbsolute(scheme, ...); }\ncatch (ArgumentNullException) when (((ArgumentNullException)ex).ParamName == \"scheme\") { /* fall back to configured scheme */ }","preventionTips":["Always call UseForwardedHeaders when behind a reverse proxy","Default scheme to http/https before URL composition","Verify Request.Scheme is non-null in integration tests"],"tags":["null-argument","scheme","reverse-proxy","http","dashboard"],"backgroundTag":"null-argument","analyzedSha":"e52b8508e54cdb7a9ce7f9fec03d9ea8ad2710fb","analyzedAt":"2026-09-14T14:46:34.677Z","contentChangedAt":"2026-09-14T14:46:34.677Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}