microsoft/aspire · error · InvalidOperationException
Foundry CLI did not return a model ID for model
Error message
Foundry CLI did not return a model ID for model '{modelName}'. What it means
GetModelIdAsync runs `foundry model info <modelName>` and attempts to parse a model ID from the output, first with the modern JSON shape (TryParseModelInfo when the daemon verb is 'server') and then with the legacy parser (TryParseModelId). If neither parser finds a model ID in the CLI's output, this InvalidOperationException is thrown — the CLI responded, but not in a shape the integration recognizes.
Solutions
- Run `foundry model info <modelName>` manually and compare its output to what the integration expects; confirm the exact model name via `foundry model list`.
- Download/compile the model first (`foundry model download <modelName>`) so `model info` returns a real model ID.
- Update the Foundry Local CLI to a version whose output matches the supported formats, then retry.
- If your CLI version emits a new format, file an issue at microsoft/aspire with the raw `model info` output so the parser can be extended.
Example fix
// before: alias that is not a downloaded model yields unparsable output
.AddModel("phi-4-mini-q4-GS", "my-model")
// after: use an alias confirmed by `foundry model list` / `foundry model search`
.AddModel("phi-4-mini", "my-model") Defensive patterns
Strategy: validation
Validate before calling
// Verify the model resolves and info output is parseable before wiring it in:
// foundry model search <modelName>
// foundry model info <modelName> --output json # must contain a model id field
var psi = new ProcessStartInfo("foundry", $"model info {modelName} --output json") { RedirectStandardOutput = true, UseShellUse = false };
using var p = Process.Start(psi)!;
var output = await p.StandardOutput.ReadToEndAsync();
bool hasModelId = output.Contains("id", StringComparison.OrdinalIgnoreCase) || output.Contains("modelId", StringComparison.OrdinalIgnoreCase); Try / catch
try
{
await model.DownloadAsync();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("did not return a model ID"))
{
logger.LogError(ex, "Could not resolve model ID for '{Model}'. Verify the name via `foundry model list` and that the CLI output format is supported.", modelName);
} Prevention
- Always use model names/aliases confirmed by `foundry model list` or `foundry model search`.
- Download the model (`foundry model download <name>`) before relying on `model info` to resolve an ID.
- Keep the CLI on a version whose `model info` output matches the supported JSON/legacy formats.
- If the raw output looks fine but still fails, capture it and file an issue so the parser can support the new format.
When it happens
Trigger: DownloadModelAsync or legacyModelId path calls GetModelIdAsync; the command exits 0 (so no exit-code error) but the output contains no recognizable model ID — e.g. the model is not downloaded/known and the CLI prints a human-readable 'not found' or empty message instead of the expected JSON or ID line.
Common situations: Requesting a model that is not present locally or misspelling its name/alias; a Foundry CLI version whose `model info` output format differs from both supported shapes (modern JSON vs legacy text); the daemon verb detection picks the wrong parsing branch for the installed CLI.
Related errors
- Foundry CLI command ' ' could not be started.
- Foundry CLI command ' ' exited before producing required…
- Foundry CLI command ' ' failed with exit code
- The installed Foundry CLI does not expose a 'server' or…
- Timed out waiting for Foundry CLI server startup after
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/ab280340e4c182f5.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Foundry/FoundryLocalService.cs:526
private static async Task<string> GetModelIdAsync(string modelName, CancellationToken cancellationToken)
{
var daemonVerb = await GetDaemonVerbAsync(cancellationToken).ConfigureAwait(false);
var arguments = daemonVerb == "server"
? new[] { "model", "info", modelName, "--output", "json" }
: new[] { "model", "info", modelName };
var output = await RunFoundryCommandAsync(arguments, onOutput: null, cancellationToken).ConfigureAwait(false);
if (daemonVerb == "server" && TryParseModelInfo(output, out var modernModelId, out _))
{
return modernModelId;
}
if (TryParseModelId(output, out var modelId))
{
return modelId;
}
throw new InvalidOperationException($"Foundry CLI did not return a model ID for model '{modelName}'.");
}
internal static bool TryParseEndpoint(string output, out Uri endpoint)
{
// Foundry CLI emits service startup lines like:
// Service is Started on http://127.0.0.1:50920/, PID 78399!
// and status lines like:
// Model management service is running on http://127.0.0.1:50920/openai/status
var match = s_urlRegex.Match(output);
if (!match.Success)
{
endpoint = null!;
return false;
}
var url = match.Value.TrimEnd(',', '.', '!', ')', ']', '}', '"', '\'');
if (!Uri.TryCreate(url, UriKind.Absolute, out var parsedEndpoint))
{View on GitHub (pinned to 25830f84bd)