{"record":{"id":"05d7bfa7ffda90b6","repo":"dotnet/yarp","slug":"invalid-destination-prefix","errorCode":null,"errorMessage":"Invalid destination prefix.","messagePattern":"Invalid destination prefix\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/ReverseProxy/Forwarder/HttpForwarder.cs","lineNumber":125,"sourceCode":"        ArgumentNullException.ThrowIfNull(requestConfig);\n        ArgumentNullException.ThrowIfNull(transformer);\n\n        if (RequestUtilities.IsResponseSet(context.Response))\n        {\n            throw new InvalidOperationException(\"The request cannot be forwarded, the response has already started\");\n        }\n\n        // HttpClient overload for SendAsync changes response behavior to fully buffered which impacts performance\n        // See discussion in https://github.com/dotnet/yarp/issues/458\n        if (httpClient is HttpClient)\n        {\n            throw new ArgumentException($\"The http client must be of type HttpMessageInvoker, not HttpClient\", nameof(httpClient));\n        }\n\n        // \"http://a\".Length = 8\n        if (destinationPrefix is null || destinationPrefix.Length < 8)\n        {\n            throw new ArgumentException(\"Invalid destination prefix.\", nameof(destinationPrefix));\n        }\n\n        ForwarderTelemetry.Log.ForwarderStart(destinationPrefix);\n\n        var activityCancellationSource = ActivityCancellationTokenSource.Rent(requestConfig?.ActivityTimeout ?? DefaultTimeout, context.RequestAborted, cancellationToken);\n        try\n        {\n            var isClientHttp2OrGreater = ProtocolHelper.IsHttp2OrGreater(context.Request.Protocol);\n\n            // NOTE: We heuristically assume gRPC-looking requests may require streaming semantics.\n            // See https://github.com/dotnet/yarp/issues/118 for design discussion.\n            var isStreamingRequest = isClientHttp2OrGreater && ProtocolHelper.IsGrpcContentType(context.Request.ContentType);\n\n            HttpRequestMessage? destinationRequest = null;\n            StreamCopyHttpContent? requestContent = null;\n            HttpResponseMessage destinationResponse;\n            try\n            {","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/src/ReverseProxy/Forwarder/HttpForwarder.cs#L107-L143","documentation":"Thrown by HttpForwarder.SendAsync when the destinationPrefix is null or shorter than 8 characters. The minimum valid prefix like \"http://a\" is 8 characters, so anything shorter cannot be a well-formed absolute URI. The forwarder needs a valid base address to construct the upstream request.","triggerScenarios":"Passing a destinationPrefix that is null, empty, or a relative/non-absolute URL shorter than 8 chars (e.g., \"http://\") to SendAsync. Usually the address comes from DestinationConfig.Address.","commonSituations":"Destination Address misconfigured in appsettings (missing scheme, trailing slash only, placeholder unresolved). Env-var/config substitution producing an empty string. Typo in the destination URL.","solutions":["Set DestinationConfig.Address to a fully-qualified absolute URL (e.g., \"http://host:port/path\") of at least 8 characters.","Validate the address has a scheme (http/https) and host before passing to SendAsync.","If using config substitution, ensure the substituted value is non-empty and well-formed."],"exampleFix":"// before\n\"Destinations\": { \"d1\": { \"Address\": \"http://\" } }\n// after\n\"Destinations\": { \"d1\": { \"Address\": \"http://backend.local:8080/\" } }","handlingStrategy":"validation","validationCode":"if (string.IsNullOrEmpty(destinationPrefix) || destinationPrefix.Length < 8 || !Uri.IsWellFormedUriString(destinationPrefix, UriKind.Absolute))\n    throw new ArgumentException(\"Invalid destination prefix.\", nameof(destinationPrefix));","typeGuard":"static bool IsValidDestinationPrefix(string? s) =>\n    !string.IsNullOrEmpty(s) && s.Length >= 8 && Uri.IsWellFormedUriString(s, UriKind.Absolute);","tryCatchPattern":"try { await forwarder.SendAsync(context, address, client, reqConfig, transformer, ct); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"Invalid destination prefix\"))\n{ logger.LogError(\"Destination address invalid: {Address}\", address); context.Response.StatusCode = 502; }","preventionTips":["Validate destination Address config at startup via YARP config validation.","Ensure config substitution never yields empty/relative URLs.","Unit-test destination URLs with Uri.IsWellFormedUriString."],"tags":["forwarder","destination","url-validation","configuration"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}