microsoft/aspire · error · InvalidOperationException
is not available because the dashboard is not enabled or…
Error message
{nameof(InteractionService)} is not available because the dashboard is not enabled or because this command is running in non-interactive CLI mode. What it means
InteractionService throws InvalidOperationException when any of its prompt methods (message box, inputs, notification, progress) is called while the service is not available. IsAvailable is false when the AppHost runs without the dashboard enabled, or when the command runs in non-interactive CLI mode where no UI exists to render prompts. The library throws eagerly instead of silently blocking or returning a default because a caller expecting user interaction cannot proceed meaningfully.
Solutions
- Check InteractionService.IsAvailable before prompting and skip or fall back to defaults when false.
- Enable the dashboard (remove dashboard disable flags / run via `aspire run` interactively) if the interaction is required.
- Wrap prompt calls in try-catch on InvalidOperationException and degrade gracefully (log, use default value) for non-interactive environments.
- Gate interaction-dependent code behind an environment/configuration check so it never runs in headless/CI contexts.
Example fix
// before
var answer = await interactionService.PromptMessageBoxAsync(new MessageBoxInteractionOptions { ... });
// after
if (interactionService.IsAvailable)
{
var answer = await interactionService.PromptMessageBoxAsync(new MessageBoxInteractionOptions { ... });
}
else
{
logger.LogInformation("Skipping prompt: dashboard not enabled or non-interactive mode.");
} Defensive patterns
Strategy: validation
Validate before calling
if (!interactionService.IsAvailable)
{
logger.LogWarning("InteractionService unavailable; using default instead of prompting.");
return defaultValue;
} Try / catch
try
{
result = await interactionService.PromptMessageBoxAsync(options);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("InteractionService"))
{
logger.LogWarning(ex, "Prompt unavailable; falling back to default.");
result = defaultValue;
} Prevention
- Always check InteractionService.IsAvailable before any prompt call.
- Never assume interactive mode: CI, publish, and non-interactive CLI runs have no dashboard.
- Provide non-interactive defaults for every prompt so headless runs can proceed.
- Test AppHosts with the dashboard disabled to surface interaction dependencies.
When it happens
Trigger: Calling InteractionService.PromptMessageBoxAsync, PromptInputsAsync, PromptNotificationAsync, or PromptProgressAsync (directly or via an eventing subscriber/resource notification) when IsAvailable is false — i.e. dashboard is disabled (ASPIRE_DASHBOARD_DISABLED or no dashboard resource) or the process runs under non-interactive CLI commands such as `aspire run` in pipelines, `aspire publish`, or CI.
Common situations: Running an AppHost in CI/CD where no dashboard is attached; invoking prompts from custom event handlers or resource lifecycle code that works locally but fails in `aspire publish` or non-interactive terminals; disabling the dashboard for performance and forgetting code depends on interactions.
Related errors
- Dashboard testing is not supported in publish mode.
- A circular lifetime reference was detected for resource
- A global MCP approval policy cannot be combined with custom…
- A security rule named
- adminPassword
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/29b887bd6a76ce23.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting/InteractionService.cs:689
yield return item;
}
}
finally
{
lock (_onInteractionUpdatedLock)
{
OnInteractionUpdated -= WriteToChannel;
}
channel.Writer.TryComplete();
}
}
private void EnsureServiceAvailable()
{
if (!IsAvailable)
{
throw new InvalidOperationException($"{nameof(InteractionService)} is not available because the dashboard is not enabled or because this command is running in non-interactive CLI mode.");
}
}
}
internal class InteractionCollection : KeyedCollection<int, Interaction>
{
protected override int GetKeyForItem(Interaction item) => item.InteractionId;
}
[DebuggerDisplay("State = {State}, Complete = {Complete}")]
internal sealed class InteractionCompletionState
{
public bool Complete { get; init; }
public object? State { get; init; }
}
[DebuggerDisplay("InteractionId = {InteractionId}, State = {State}, Title = {Title}")]
internal class InteractionView on GitHub (pinned to 25830f84bd)