{"record":{"id":"9e1eddbaa1ee2f98","repo":"dotnet/yarp","slug":"the-route-config-format-has-changed-routes-are-no","errorCode":null,"errorMessage":"The route config format has changed, routes are now objects instead of an array. The route id must be set as the object name, not with the 'RouteId' field.","messagePattern":"The route config format has changed, routes are now objects instead of an array\\. The route id must be set as the object name, not with the 'RouteId' field\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/ReverseProxy/Configuration/ConfigProvider/ConfigurationConfigProvider.cs","lineNumber":142,"sourceCode":"    private static RouteConfig CreateRoute(IConfigurationSection section)\n    {\n        if (!string.IsNullOrEmpty(section[\"RouteId\"]))\n        {\n            throw new Exception(\"The route config format has changed, routes are now objects instead of an array. The route id must be set as the object name, not with the 'RouteId' field.\");\n        }\n\n        return new RouteConfig\n        {\n            RouteId = section.Key,\n            Order = section.ReadInt32(nameof(RouteConfig.Order)),\n            MaxRequestBodySize = section.ReadInt64(nameof(RouteConfig.MaxRequestBodySize)),","sourceCodeStart":null,"sourceCodeEnd":null,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/src/ReverseProxy/Configuration/ConfigurationConfigProvider.cs#L142","documentation":"Thrown by ConfigurationConfigProvider.CreateRoute when a route configuration section contains a \"RouteId\" field. YARP changed its config schema: routes are now keyed objects (the key IS the route id) rather than an array of objects with a RouteId property. This guard detects legacy config and tells the user to migrate to the object-keyed format.","triggerScenarios":"Loading proxy config from appsettings.json (or any IConfigurationSource) where the Routes section is an array with explicit RouteId fields, e.g., \"Routes\": [ { \"RouteId\": \"myroute\", ... } ] instead of \"Routes\": { \"myroute\": { ... } }.","commonSituations":"Upgrading YARP from an older version that used the array format. Copying config from outdated documentation or samples. Mixing the old array syntax into a newer YARP config file.","solutions":["Convert the Routes section from an array to an object keyed by route id, moving the id out of RouteId into the object key.","Remove the RouteId field from each route entry; the section key becomes the route id.","Consult current YARP docs for the object-keyed route config schema."],"exampleFix":"// before — appsettings.json (legacy array)\n\"Routes\": [\n  { \"RouteId\": \"route1\", \"ClusterId\": \"cluster1\", \"Match\": { \"Path\": \"/api\" } }\n]\n// after — object-keyed\n\"Routes\": {\n  \"route1\": { \"ClusterId\": \"cluster1\", \"Match\": { \"Path\": \"/api\" } }\n}","handlingStrategy":"validation","validationCode":"foreach (var routeSection in config.GetSection(\"Routes\").GetChildren())\n{\n    if (!string.IsNullOrEmpty(routeSection[\"RouteId\"]))\n        throw new InvalidOperationException(\"Migrate Routes to object-keyed format (remove RouteId). \");\n}","typeGuard":"// n/a — config schema check, not type narrowing","tryCatchPattern":"try { builder.Services.AddReverseProxy().LoadFromConfig(config); }\ncatch (Exception ex) when (ex.Message.Contains(\"route config format has changed\"))\n{ logger.LogError(ex, \"Migrate appsettings Routes from array to object-keyed.\"); throw; }","preventionTips":["After YARP upgrades, run the config validator / read the migration notes.","Keep route config as object-keyed format from the start.","Add a CI test that loads the config to catch schema regressions."],"tags":["configuration","schema-migration","config-provider","startup"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}