dotnet/yarp · error · InvalidOperationException
IProxyConfig.ChangeToken has a null value.
Error message
IProxyConfig.ChangeToken has a null value.
What it means
After confirming `GetConfig()` returned non-null, YARP validates that `IProxyConfig.ChangeToken` is not null. The change token is essential because `ProxyConfigManager` uses it to detect config changes and trigger hot reloads. A null change token means YARP can never detect updates, so it refuses to start with this configuration.
Source
Thrown at src/ReverseProxy/Management/ProxyConfigManager.cs:337
Log.ErrorReloadingConfig(_logger, ex);
foreach (var configChangeListener in _configChangeListeners)
{
configChangeListener.ConfigurationLoadingFailed(instance.Provider, ex);
}
}
}
private static void ValidateConfigProperties(IProxyConfig config)
{
if (config is null)
{
throw new InvalidOperationException($"{nameof(IProxyConfigProvider.GetConfig)} returned a null value.");
}
if (config.ChangeToken is null)
{
throw new InvalidOperationException($"{nameof(IProxyConfig.ChangeToken)} has a null value.");
}
}
private ValueTask<IProxyConfig> LoadConfigAsync(IProxyConfigProvider provider, CancellationToken cancellationToken)
{
var config = provider.GetConfig();
ValidateConfigProperties(config);
if (_destinationResolver.GetType() == typeof(NoOpDestinationResolver))
{
return new(config);
}
return LoadConfigAsyncCore(config, cancellationToken);
}
private async ValueTask<IProxyConfig> LoadConfigAsyncCore(IProxyConfig config, CancellationToken cancellationToken)
{View on GitHub (pinned to bd11867bee)
Solutions
- In the custom `IProxyConfig` implementation, always provide a valid `IChangeToken` for `ChangeToken` — use a `CancellationChangeToken` backed by a `CancellationTokenSource` for reload support.
- If reloads are not needed, return `NullChangeToken.Singleton` (or a new `CancellationChangeToken(new CancellationTokenSource().Token)`) as a no-op token.
- Use the built-in `InMemoryConfigProvider` as a template — it manages a `CancellationTokenSource` and exposes it as the change token.
- Add a constructor or factory that always initializes the `ChangeToken` property, preventing null at the source.
Example fix
// before — ChangeToken left null
public class MyProxyConfig : IProxyConfig
{
public IReadOnlyList<RouteConfig> Routes { get; set; }
public IReadOnlyList<ClusterConfig> Clusters { get; set; }
public IChangeToken ChangeToken { get; set; } // null!
}
// after — always provide a valid change token
public class MyProxyConfig : IProxyConfig
{
private readonly CancellationTokenSource _cts = new();
public IReadOnlyList<RouteConfig> Routes { get; init; } = Array.Empty<RouteConfig>();
public IReadOnlyList<ClusterConfig> Clusters { get; init; } = Array.Empty<ClusterConfig>();
public IChangeToken ChangeToken => new CancellationChangeToken(_cts.Token);
internal void TriggerReload() { _cts.Cancel(); }
} Defensive patterns
Strategy: validation
Validate before calling
// Validate ChangeToken before returning config
public IProxyConfig GetConfig()
{
var config = BuildConfig();
if (config?.ChangeToken is null)
throw new InvalidOperationException("ProxyConfig must have a non-null ChangeToken");
return config;
} Type guard
static bool HasValidChangeToken(IProxyConfig? config)
=> config?.ChangeToken is not null; Try / catch
// Not applicable — fix the IProxyConfig implementation to always provide a ChangeToken.
Prevention
- Always initialize ChangeToken in custom IProxyConfig implementations — use a CancellationChangeToken.
- Use NullChangeToken.Singleton if reload notifications are not needed.
- Base custom config classes on InMemoryConfigProvider patterns that handle this correctly.
When it happens
Trigger: A custom `IProxyConfig` implementation (or a custom `IProxyConfigProvider` that constructs one) does not initialize the `ChangeToken` property. During `ValidateConfigProperties` (line 335), the null check fails and throws. The exception propagates through `LoadConfigAsync` and up through the `InitialLoadAsync` wrapper.
Common situations: A developer creates a custom `IProxyConfig` class and forgets to set the `ChangeToken` property. A provider manually constructs config objects without using the built-in `ConfigurationConfigProvider` or `InMemoryConfigProvider` which handle this correctly. A config reload path creates a new config object but doesn't carry over the change token.
Related errors
- IProxyConfigProvider.GetConfig returned a null value.
- The route config format has changed, routes are now objects
- At least one IProxyConfigProvider is required.
- Unable to load or apply the proxy configuration.
- Configuration Filter Error: Substitution for '{lookup}' in c
AI-assisted analysis of dotnet/yarp@bd11867bee (2026-08-13).
Data as JSON: /api/errors/b8f637290958950d.
Report an issue: GitHub.