{"record":{"id":"6f499fb837e146a0","repo":"dotnet/yarp","slug":"a-non-empty-custommetadata-value-is-required","errorCode":null,"errorMessage":"A non-empty CustomMetadata value is required","messagePattern":"A non-empty CustomMetadata value is required","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"samples/ReverseProxy.Transforms.Sample/MyTransformProvider.cs","lineNumber":45,"sourceCode":"            // Check all clusters for a custom property and validate the associated transform data.\n            if (context.Cluster.Metadata?.TryGetValue(\"CustomMetadata\", out var value) ?? false)\n            {\n                if (string.IsNullOrEmpty(value))\n                {\n                    context.Errors.Add(new ArgumentException(\"A non-empty CustomMetadata value is required\"));\n                }\n            }\n        }\n\n        public void Apply(TransformBuilderContext transformBuildContext)\n        {\n            // Check all routes for a custom property and add the associated transform.\n            if ((transformBuildContext.Route.Metadata?.TryGetValue(\"CustomMetadata\", out var value) ?? false)\n                || (transformBuildContext.Cluster?.Metadata?.TryGetValue(\"CustomMetadata\", out value) ?? false))\n            {\n                if (string.IsNullOrEmpty(value))\n                {\n                    throw new ArgumentException(\"A non-empty CustomMetadata value is required\");\n                }\n\n                transformBuildContext.AddRequestTransform(transformContext =>\n                {\n                    transformContext.ProxyRequest.Options.Set(new HttpRequestOptionsKey<string>(\"CustomMetadata\"), value);\n                    return default;\n                });\n            }\n        }\n    }\n}\n","sourceCodeStart":27,"sourceCodeEnd":57,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/samples/ReverseProxy.Transforms.Sample/MyTransformProvider.cs#L27-L57","documentation":"Thrown by the MyTransformProvider sample (ITransformProvider.Apply) when route or cluster Metadata contains the key \"CustomMetadata\" with a null or empty value. Unlike the validation-phase methods (which add to context.Errors), Apply throws directly because it cannot construct the request transform without a value. This is sample code demonstrating metadata-driven transforms.","triggerScenarios":"A RouteConfig.Metadata or ClusterConfig.Metadata dictionary has an entry \"CustomMetadata\" mapped to \"\" or null. Apply runs during the transform-building phase when the proxy pipeline is assembled for the route/cluster.","commonSituations":"Metadata key added in config but value left empty. Migrating from a transform-values approach to a metadata approach and forgetting to populate the value.","solutions":["Set a non-empty value for CustomMetadata in the route or cluster Metadata dictionary.","Remove the CustomMetadata metadata key if the transform is not intended for that route/cluster.","Ensure ValidateRoute/ValidateCluster (which also flag this) catch the problem at startup before Apply throws at request time."],"exampleFix":"// before — appsettings.json route metadata\n\"Metadata\": { \"CustomMetadata\": \"\" }\n// after\n\"Metadata\": { \"CustomMetadata\": \"some-value\" }","handlingStrategy":"validation","validationCode":"if ((route.Metadata?.TryGetValue(\"CustomMetadata\", out var v) ?? false) && string.IsNullOrEmpty(v))\n{\n    context.Errors.Add(new ArgumentException(\"A non-empty CustomMetadata value is required\"));\n}","typeGuard":"static bool IsValidCustomMetadata(string? v) => !string.IsNullOrWhiteSpace(v);","tryCatchPattern":"try { provider.Apply(transformBuildContext); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"CustomMetadata\"))\n{ logger.LogWarning(ex, \"Skipping metadata transform\"); }","preventionTips":["Implement ValidateRoute/ValidateCluster to catch empty metadata at startup.","Keep metadata schema documented alongside route config.","Lint config files for empty metadata values in CI."],"tags":["transforms","configuration","metadata","validation","sample"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}