{"record":{"id":"0f8b988d8f90167d","repo":"microsoft/aspire","slug":"live-rendering-requires-interactive-output","errorCode":null,"errorMessage":"Live rendering requires interactive output.","messagePattern":"Live rendering requires interactive output\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Cli/Interaction/ConsoleInteractionService.cs","lineNumber":648,"sourceCode":"            else\n            {\n                MessageConsole.MarkupLine($\"[red]{line.EscapeMarkup()}[/]\");\n            }\n        }\n    }\n\n    public void DisplayRenderable(IRenderable renderable)\n    {\n        MessageConsole.Write(renderable);\n    }\n\n    public async Task DisplayLiveAsync(IRenderable initialRenderable, Func<Action<IRenderable>, Task> callback)\n    {\n        if (!_hostEnvironment.SupportsInteractiveOutput)\n        {\n            // The callback supplies replacement snapshots, so appending them would duplicate prior\n            // content. Callers must define incremental static output when a live region is unavailable.\n            throw new InvalidOperationException(\"Live rendering requires interactive output.\");\n        }\n\n        await MessageConsole.Live(initialRenderable)\n            .AutoClear(false)\n            .StartAsync(async ctx =>\n            {\n                await callback(renderable => ctx.UpdateTarget(renderable));\n            });\n    }\n\n    public void DisplayCancellationMessage(string? message = null, ConsoleOutput? consoleOverride = null)\n    {\n        GetConsoleOutput(consoleOverride).WriteLine();\n        DisplayMessage(KnownEmojis.StopSign, $\"[teal bold]{message ?? InteractionServiceStrings.StoppingAspire}[/]\", allowMarkup: true, consoleOverride: consoleOverride);\n    }\n\n    public async Task<bool> PromptConfirmAsync(string promptText, PromptBinding<bool>? binding = null, CancellationToken cancellationToken = default)\n    {","sourceCodeStart":630,"sourceCodeEnd":666,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Cli/Interaction/ConsoleInteractionService.cs#L630-L666","documentation":"DisplayLiveAsync renders a continuously updated console region (Spectre.Console live display). It requires an interactive output environment; when _hostEnvironment.SupportsInteractiveOutput is false it throws this InvalidOperationException, telling the caller to fall back to incremental static output because the callback's replacement snapshots would otherwise duplicate already-printed content.","triggerScenarios":"Calling DisplayLiveAsync while the CLI output is redirected (non-TTY), --non-interactive is set, or the host environment reports non-interactive output.","commonSituations":"Running progress-rendering commands (e.g. run/deploy with live step updates) in CI logs or piped output; invoking the interaction service from a test host without an interactive console.","solutions":["Check _hostEnvironment.SupportsInteractiveOutput before calling and print incremental static lines instead.","Catch InvalidOperationException around DisplayLiveAsync and fall back to non-live rendering.","Run the command in a real terminal for live rendering.","Refactor the rendering callback to supply append-only output when live regions are unavailable."],"exampleFix":"// before\nawait interaction.DisplayLiveAsync(initial, updateCallback);\n// after\nif (hostEnvironment.SupportsInteractiveOutput)\n{\n    await interaction.DisplayLiveAsync(initial, updateCallback);\n}\nelse\n{\n    await RenderStaticIncrementallyAsync(interaction, updateCallback);\n}","handlingStrategy":"fallback","validationCode":"if (!hostEnvironment.SupportsInteractiveOutput)\n{\n    await RenderStaticIncrementallyAsync(interaction, updateCallback);\n    return;\n}","typeGuard":"bool liveRenderingSupported = hostEnvironment.SupportsInteractiveOutput;","tryCatchPattern":"try { await interaction.DisplayLiveAsync(initial, cb); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Live rendering\"))\n{\n    await RenderStaticIncrementallyAsync(interaction, cb);\n}","preventionTips":["Always gate live rendering on SupportsInteractiveOutput.","Design render callbacks so static incremental output is possible.","Run live-UI commands in a TTY only.","Add a non-TTY test that exercises the static fallback."],"tags":["cli","non-interactive","live-rendering","console"],"backgroundTag":"unsupported-operation","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}