`altool workspace compile` crashes with `IOException: The handle is invalid` when stdout is redirected (v17.0.2273547)
Nobody has claimed this yet.
- Dominant language
- PowerShell
- Stars
- 881
- Forks
- 285
- Avg merge
- 3d 36m
- Merged PRs (30d)
- 1
Description
Summary
altool workspace compile throws an unhandled System.IO.IOException: The handle is invalid during CompilationStatus.UpdateProgress() when invoked from a non-interactive shell (pipes, CI runners, redirected output). The compilation never actually runs ÔÇö the crash happens almost immediately after the "Starting compilation" banner.
Environment
- AL Language extension: 17.0.2273547 (published 2026-04-01)
- OS: Windows 11 Pro for Workstations 10.0.26200
- .NET 8.0.25 runtime
- Shell: Git Bash (non-interactive / redirected stdout)
Reproduction
altool.exe workspace compile "path/to/workspace.code-workspace" 2>&1 | tail -80
Any redirection of stdout triggers it ÔÇö | tee, > file.log, piping through head/tail, or running inside a CI runner that captures the child process's streams.
Running the same command directly in a Windows Terminal / cmd.exe window with no redirection works correctly.
Expected
When stdout is not a TTY, workspace compile should disable the interactive progress display and emit plain line-by-line status output (or at least guard the Console.WindowWidth call and fall back to a sensible default). Competing CLI tools (e.g. dotnet build, msbuild) degrade gracefully under redirection.
Actual
Starting compilation of 2 project(s) with 22 parallel task(s)...
Log directory: C:\Repos\...\logs
Unhandled exception. System.IO.IOException: The handle is invalid.
at System.ConsolePal.GetBufferInfo(Boolean throwOnNoConsole, Boolean& succeeded)
at System.ConsolePal.get_WindowWidth()
at Microsoft.Dynamics.Nav.Tool.CompilationStatus.UpdateProgress() in X:\source\Prod\altool\Workspace\WorkspaceCompileCommand.cs:line 130
at Microsoft.Dynamics.Nav.Tool.WorkspaceCompileCommand.<>c__DisplayClass17_0.<CompileGraphWithConcurrency>b__0(Object _) in X:\source\Prod\altool\Workspace\WorkspaceCompileCommand.cs:line 766
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.TimerQueueTimer.Fire(Boolean isThreadPool)
at System.Threading.TimerQueue.FireNextTimers()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
Process exits with a non-zero code and no logs/ output is written (the directory is created but remains empty), so CI pipelines lose both the build result and the diagnostic trail.
Suggested fix
Guard the Console.WindowWidth call in CompilationStatus.UpdateProgress(). The standard .NET idiom is:
int width;
try { width = Console.IsOutputRedirected ? 120 : Console.WindowWidth; }
catch (IOException) { width = 120; }
Or simpler: skip progress updates entirely when Console.IsOutputRedirected == true.
Impact
Blocks altool workspace compile from use in automation scenarios ÔÇö CI pipelines, Git hooks, scripted multi-project builds, and agentic tooling that captures subprocess output. Any wrapper that redirects the child's stdout hits this immediately.
As a workaround, direct alc.exe invocation per project works fine under redirection ÔÇö only the workspace-level orchestration is affected.
Internal work item: AB#631155
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with Workspace/WorkspaceCompileCommand.cs, especially CompilationStatus.UpdateProgress() around line 130, and reproduce using the redirected-output command in the issue. Confirm that workspace compilation no longer crashes under stdout redirection, produces status output or safely skips interactive progress, and preserves diagnostic logs.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100