dotnet/yarp · error · ArgumentException
Configuration Filter Error: Substitution for '{lookup}' in c
Error message
Configuration Filter Error: Substitution for '{lookup}' in cluster '{d.Key}' not found as an environment variable. What it means
Thrown by the CustomConfigFilter sample when a destination address contains a {{EnvVarName}} placeholder but the named environment variable is unset or whitespace. The filter iterates cluster destinations, regex-matches {{key}} tokens, and resolves them via Environment.GetEnvironmentVariable, failing if the lookup yields nothing. This is sample-only behavior demonstrating IProxyConfigFilter, not built into the runtime.
Source
Thrown at samples/ReverseProxy.ConfigFilter.Sample/CustomConfigFilter.cs:40
// as an environment variable. This is useful when hosted in Azure etc, as it enables a simple way to replace
// destination addresses via the management console
public ValueTask<ClusterConfig> ConfigureClusterAsync(ClusterConfig origCluster, CancellationToken cancel)
{
// Each cluster has a dictionary of destinations, which is read-only, so we'll create a new one with our updates
var newDests = new Dictionary<string, DestinationConfig>(StringComparer.OrdinalIgnoreCase);
foreach (var d in origCluster.Destinations)
{
var origAddress = d.Value.Address;
if (_exp.IsMatch(origAddress))
{
// Get the name of the env variable from the destination and lookup value
var lookup = _exp.Matches(origAddress)[0].Groups[1].Value;
var newAddress = System.Environment.GetEnvironmentVariable(lookup);
if (string.IsNullOrWhiteSpace(newAddress))
{
throw new System.ArgumentException($"Configuration Filter Error: Substitution for '{lookup}' in cluster '{d.Key}' not found as an environment variable.");
}
// using c# 9 "with" to clone and initialize a new record
var modifiedDest = d.Value with { Address = newAddress };
newDests.Add(d.Key, modifiedDest);
}
else
{
newDests.Add(d.Key, d.Value);
}
}
return new ValueTask<ClusterConfig>(origCluster with { Destinations = newDests });
}
public ValueTask<RouteConfig> ConfigureRouteAsync(RouteConfig route, ClusterConfig cluster, CancellationToken cancel)
{
// Example: do not let config based routes take priority over code based routes.
// Lower numbers are higher priority. Code routes default to 0.View on GitHub (pinned to bd11867bee)
Solutions
- Set the referenced environment variable (e.g., export MyServiceHost=backend.internal) in the environment where YARP runs.
- Verify the placeholder name in the destination address exactly matches the environment variable name (case-sensitive on Linux).
- If the variable should be optional, wrap the lookup in a try/catch or provide a default instead of throwing.
- Use configuration-based substitution (e.g., appsettings.json with ${VAR} and a configuration provider) rather than the sample filter for production.
Example fix
// before — destination address in appsettings.json
"Address": "https://{{BackendHost}}/api"
// after — set the env var before launch
// bash: export BackendHost=10.0.0.5
// or hardcode: "Address": "https://10.0.0.5/api" Defensive patterns
Strategy: validation
Validate before calling
string lookup = "MyServiceHost";
var resolved = Environment.GetEnvironmentVariable(lookup);
if (string.IsNullOrWhiteSpace(resolved))
{
throw new InvalidOperationException($"Set the '{lookup}' environment variable before starting the proxy.");
}
// safe to use resolved in destination address Type guard
// n/a — env var resolution is runtime string-based, not type-narrowing
Try / catch
try
{
config = filter.ConfigureClusterAsync(cluster, ct).AsTask().Result;
}
catch (ArgumentException ex) when (ex.Message.Contains("not found as an environment variable"))
{
logger.LogError(ex, "Environment variable substitution failed at startup; check env config.");
throw;
} Prevention
- Document every {{Placeholder}} name and require it in deployment runbooks.
- Add a startup health check that asserts all expected env vars are set before serving traffic.
- Use machine/environment-agnostic config and inject secrets via a secrets manager.
When it happens
Trigger: A cluster destination Address is set to a value like "https://{{MyServiceHost}}/path" and the environment has no MyServiceHost variable (or it is empty/whitespace) when the proxy configuration is loaded. The exception surfaces during ConfigureClusterAsync at startup or on config reload.
Common situations: Forgetting to set the environment variable in the deployment environment (Azure App Service, containers, local dev). Typo between the placeholder name and the actual env var name. Variable set in one environment (dev) but missing in another (staging/prod). Using a placeholder syntax that doesn't match the {{\w+}} regex.
Related errors
- A non-empty CustomTransform value is required
- A non-empty CustomMetadata value is required
- The route config format has changed, routes are now objects
- At least one IProxyConfigProvider is required.
- Unable to load or apply the proxy configuration.
AI-assisted analysis of dotnet/yarp@bd11867bee (2026-08-13).
Data as JSON: /api/errors/7a2ba83a98ddea34.
Report an issue: GitHub.