{"record":{"id":"44e5fbebc48bd7ac","repo":"dotnet/yarp","slug":"tconsumer-must-implement-at-least-one-i-telemetryc","errorCode":null,"errorMessage":"TConsumer must implement at least one I*TelemetryConsumer interface.","messagePattern":"TConsumer must implement at least one I\\*TelemetryConsumer interface\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/TelemetryConsumption/TelemetryConsumptionExtensions.cs","lineNumber":139,"sourceCode":"            services.AddSingleton(services => (INameResolutionTelemetryConsumer)services.GetRequiredService<TConsumer>());\n            implementsAny = true;\n        }\n\n        if (typeof(INetSecurityTelemetryConsumer).IsAssignableFrom(typeof(TConsumer)))\n        {\n            services.AddSingleton(services => (INetSecurityTelemetryConsumer)services.GetRequiredService<TConsumer>());\n            implementsAny = true;\n        }\n\n        if (typeof(ISocketsTelemetryConsumer).IsAssignableFrom(typeof(TConsumer)))\n        {\n            services.AddSingleton(services => (ISocketsTelemetryConsumer)services.GetRequiredService<TConsumer>());\n            implementsAny = true;\n        }\n\n        if (!implementsAny)\n        {\n            throw new ArgumentException(\"TConsumer must implement at least one I*TelemetryConsumer interface.\", nameof(TConsumer));\n        }\n\n        services.TryAddSingleton<TConsumer>();\n\n        services.AddTelemetryListeners();\n\n        return services;\n    }\n\n    /// <summary>\n    /// Registers a consumer singleton for every IMetricsConsumer interface it implements.\n    /// </summary>\n    public static IServiceCollection AddMetricsConsumer(this IServiceCollection services, object consumer)\n    {\n        var implementsAny = false;\n\n        if (consumer is IMetricsConsumer<ForwarderMetrics> forwarderMetricsConsumer)\n        {","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/src/TelemetryConsumption/TelemetryConsumptionExtensions.cs#L121-L157","documentation":"The generic AddTelemetryConsumer<TConsumer>() probes typeof(TConsumer) with IsAssignableFrom for each I*TelemetryConsumer interface and registers a forwarding factory for each match. Because there is no generic constraint enforcing the interface, the check is performed at runtime; if TConsumer implements none, it throws ArgumentException(paramName: TConsumer).","triggerScenarios":"Calling services.AddTelemetryConsumer<MyClass>() where MyClass does not implement any I*TelemetryConsumer interface. The error appears at startup during DI registration, not at compile time.","commonSituations":"Forgetting to add the interface to the consumer class; renaming the interface during a version upgrade so the class no longer satisfies it; passing a metrics-only type to the telemetry generic overload.","solutions":["Decorate TConsumer with at least one I*TelemetryConsumer interface.","If the type only implements IMetricsConsumer<...>, switch to AddMetricsConsumer<TConsumer>().","Add a compile-time guard: `where TConsumer : IHttpClientTelemetryConsumer` on a custom wrapper if you want the error at build time."],"exampleFix":"// before\npublic class MyConsumer { ... }\nservices.AddTelemetryConsumer<MyConsumer>();\n\n// after\npublic class MyConsumer : ISocketsTelemetryConsumer { ... }\nservices.AddTelemetryConsumer<MyConsumer>();","handlingStrategy":"type-guard","validationCode":"static bool ImplementsAnyTelemetryConsumer<T>() =>\n    typeof(IHttpClientTelemetryConsumer).IsAssignableFrom(typeof(T))\n    || typeof(ISocketsTelemetryConsumer).IsAssignableFrom(typeof(T))\n    || typeof(INetSecurityTelemetryConsumer).IsAssignableFrom(typeof(T));\n\nif (ImplementsAnyTelemetryConsumer<MyConsumer>())\n    services.AddTelemetryConsumer<MyConsumer>();","typeGuard":"// Prefer a compile-time constraint on a custom wrapper:\npublic static IServiceCollection AddMyTelemetryConsumer<TConsumer>(this IServiceCollection services)\n    where TConsumer : class, IHttpClientTelemetryConsumer\n    => services.AddTelemetryConsumer<TConsumer>();","tryCatchPattern":null,"preventionTips":["Add a generic constraint on your own registration extension so misuse fails at compile time.","Re-run the consumer's unit tests after upgrading YARP, in case an interface moved namespace.","Document which interfaces each consumer implements at the class level."],"tags":["telemetry","di-registration","interface","generic","validation","yarp"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}