{"record":{"id":"eebfd01aaf7b76a4","repo":"microsoft/aspire","slug":"the-microsoft-foundry-model-catalog-produced-no-model","errorCode":null,"errorMessage":"The Microsoft Foundry model catalog produced no model descriptors after filtering. Refusing to overwrite the generated model descriptors with an empty catalog.","messagePattern":"The Microsoft Foundry model catalog produced no model descriptors after filtering\\. Refusing to overwrite the generated model descriptors with an empty catalog\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Foundry/tools/GenModel.cs","lineNumber":35,"sourceCode":"using Markdig.Syntax;\nusing Markdig.Syntax.Inlines;\n\nvar isFoundryLocal = args.Contains(\"--local\");\n\nusing var mc = new ModelClient(isFoundryLocal);\nvar allModelsResponse = await mc.GetAllModelsAsync().ConfigureAwait(false);\nvar models = allModelsResponse.Entities ?? [];\nif (models.Count == 0)\n{\n    throw new InvalidOperationException(\"The Microsoft Foundry model catalog returned no models. Refusing to overwrite the generated model descriptors with an empty catalog.\");\n}\n\nvar descriptorModels = isFoundryLocal\n    ? GetLocalDescriptorModels(models)\n    : GetDistinctHostedModels(models).ToList();\nif (descriptorModels.Count == 0)\n{\n    throw new InvalidOperationException(\"The Microsoft Foundry model catalog produced no model descriptors after filtering. Refusing to overwrite the generated model descriptors with an empty catalog.\");\n}\n\n// Generate C# extension methods for the models\nvar generatedCode = isFoundryLocal\n    ? GenerateLocalCode(\"Aspire.Hosting.Foundry\", descriptorModels)\n    : GenerateHostedCode(\"Aspire.Hosting.Foundry\", descriptorModels);\n\n// Write the generated code to a file\nvar filename = isFoundryLocal\n    ? Path.Combine(\"..\", \"FoundryModel.Local.Generated.cs\")\n    : Path.Combine(\"..\", \"FoundryModel.Generated.cs\");\n\nFile.WriteAllText(filename, generatedCode);\nConsole.WriteLine($\"Generated extension methods written to {Path.GetFileName(filename)}\");\n\n// Also serialize the strongly typed response for output with pretty printing\nvar options = new JsonSerializerOptions\n{","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Foundry/tools/GenModel.cs#L17-L53","documentation":"GenModel.cs filters the fetched Foundry model list into descriptor models (via GetLocalDescriptorModels or GetDistinctHostedModels). If every model is filtered out, regenerating would overwrite the generated extension methods with an empty set, so the tool throws rather than clobbering the checked-in generated code. Unlike error 970, the raw catalog had models but none survived filtering.","triggerScenarios":"Running GenModel when models.Count > 0 but descriptorModels.Count == 0 after applying GetLocalDescriptorModels (local catalog filters) or GetDistinctHostedModels (dedup/hosting filters).","commonSituations":"Foundry changed model metadata (e.g. lifecycle/name/ SKU fields) so filters no longer match; running with isFoundryLocal=true against an endpoint whose models don't match local-descriptor criteria; newly renamed models dropping out of the distinct-hosted grouping.","solutions":["Dump the intermediate model list and check which filter (local vs hosted) eliminates all entries; update the filter logic for changed catalog metadata.","Run against the correct endpoint for the chosen mode (isFoundryLocal) — mismatched endpoints yield models that fail the other mode's filters.","Compare the current API response schema to the ApiResponse model classes and update deserialization if Foundry renamed fields used by the filters.","If the catalog legitimately no longer contains supported models, coordinate a deliberate removal of generated code instead of letting the tool fail."],"exampleFix":"// diagnostic before throwing\nclassifier: var local = GetLocalDescriptorModels(models).ToList();\nvar hosted = GetDistinctHostedModels(models).ToList();\nConsole.WriteLine($\"raw={models.Count} local={local.Count} hosted={hosted.Count}\");","handlingStrategy":"validation","validationCode":"var descriptorModels = isFoundryLocal\n    ? GetLocalDescriptorModels(models).ToList()\n    : GetDistinctHostedModels(models).ToList();\nif (descriptorModels.Count == 0 && models.Count > 0)\n{\n    Console.WriteLine($\"All {models.Count} catalog models were filtered out; inspect filter logic before regenerating.\");\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    await RunGenModelAsync();\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"produced no model descriptors after filtering\"))\n{\n    // do not overwrite generated code; investigate filters/metadata drift\n}","preventionTips":["Log raw vs filtered counts on every codegen run","Update filter predicates whenever Foundry model metadata schema changes","Snapshot catalog responses to detect drift early","Run codegen in CI with a diff check so silent filter drops are caught"],"tags":["code-generation","empty-result-set","filtering","azure-foundry"],"backgroundTag":"empty-result-set","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}