{"record":{"id":"c4ac665313ae7364","repo":"dotnet/yarp","slug":"iproxyconfigprovider-getconfig-returned-a-null-val","errorCode":null,"errorMessage":"IProxyConfigProvider.GetConfig returned a null value.","messagePattern":"IProxyConfigProvider\\.GetConfig returned a null value\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ReverseProxy/Management/ProxyConfigManager.cs","lineNumber":332,"sourceCode":"        ListenForConfigChanges();\n\n        void OnConfigLoadError(ConfigState instance, Exception ex)\n        {\n            instance.LoadFailed = true;\n            Log.ErrorReloadingConfig(_logger, ex);\n\n            foreach (var configChangeListener in _configChangeListeners)\n            {\n                configChangeListener.ConfigurationLoadingFailed(instance.Provider, ex);\n            }\n        }\n    }\n\n    private static void ValidateConfigProperties(IProxyConfig config)\n    {\n        if (config is null)\n        {\n            throw new InvalidOperationException($\"{nameof(IProxyConfigProvider.GetConfig)} returned a null value.\");\n        }\n\n        if (config.ChangeToken is null)\n        {\n            throw new InvalidOperationException($\"{nameof(IProxyConfig.ChangeToken)} has a null value.\");\n        }\n    }\n\n    private ValueTask<IProxyConfig> LoadConfigAsync(IProxyConfigProvider provider, CancellationToken cancellationToken)\n    {\n        var config = provider.GetConfig();\n        ValidateConfigProperties(config);\n\n        if (_destinationResolver.GetType() == typeof(NoOpDestinationResolver))\n        {\n            return new(config);\n        }\n","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/src/ReverseProxy/Management/ProxyConfigManager.cs#L314-L350","documentation":"When `ProxyConfigManager` calls `IProxyConfigProvider.GetConfig()`, it validates the returned object is not null. A null return is treated as a provider bug — the contract requires a non-null `IProxyConfig` instance. This check runs during both initial load and config reloads, and the exception propagates up through the `InitialLoadAsync` wrapper (error 27).","triggerScenarios":"A custom `IProxyConfigProvider` implementation's `GetConfig()` method returns `null` — typically due to a missing `return` statement, a conditional that doesn't cover all paths, or a logic error where the config object is constructed only under certain conditions.","commonSituations":"A developer writes a custom config provider and forgets to return the config object in an edge case. A provider dynamically loads config from an external source (e.g., a database or API) and returns null when the source is unavailable instead of throwing or returning an empty config.","solutions":["In the custom `IProxyConfigProvider.GetConfig()` implementation, ensure every code path returns a non-null `IProxyConfig` — add a fallback that returns an empty config rather than null.","Return an `IProxyConfig` with empty routes and clusters lists if no configuration is available, rather than returning null.","Throw a descriptive exception from `GetConfig()` if config cannot be loaded, so the failure is explicit rather than a null contract violation.","Enable nullable reference types (`<Nullable>enable</Nullable>`) so the compiler flags null-returning paths at build time.","Add a unit test that calls `GetConfig()` and asserts the result is non-null."],"exampleFix":"// before — returns null when no config loaded\npublic IProxyConfig GetConfig()\n{\n    if (_loadedConfig is null)\n        return null; // bug!\n    return _loadedConfig;\n}\n// after — always returns a valid IProxyConfig\npublic IProxyConfig GetConfig()\n{\n    return _loadedConfig ?? new InMemoryConfig(\n        routes: Array.Empty<RouteConfig>(),\n        clusters: Array.Empty<ClusterConfig>());\n}","handlingStrategy":"validation","validationCode":"// Validate your provider before registration\npublic IProxyConfig GetConfig()\n{\n    var config = BuildConfig();\n    if (config is null)\n        throw new InvalidOperationException(\"Failed to build proxy config from source\");\n    return config;\n}","typeGuard":"static bool IsValidProxyConfig(IProxyConfig? config)\n    => config is not null && config.ChangeToken is not null;","tryCatchPattern":"// Not applicable — fix the provider to never return null. This is a contract violation.","preventionTips":["In custom IProxyConfigProvider implementations, ensure every code path in GetConfig() returns non-null.","Return an empty InMemoryConfig rather than null when no config data is available.","Enable nullable reference types so the compiler flags null-returning paths."],"tags":["configuration","config-provider","null-reference","contract-violation","custom-provider"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}