Repository navigation
Windows: copilot.exe exits 1 with empty streams when stdout is a pipe / regular file (FlushFileBuffers ERROR_INVALID_FUNCTION) — breaks all non-PowerShell automation on v1.0.44-0 #3188
Description
Summary
GitHub Copilot CLI (copilot.exe, v1.0.44-0 on Windows) exits with code 1 and produces empty stdout / empty stderr when invoked from a child process whose stdout handle is anything other than a PowerShell native > redirect (or an interactive console).
When stdout is set to DEVNULL and stderr is captured separately, the underlying error becomes visible:
Error: Failed to sync '<stdout>': Incorrect function.
This is ERROR_INVALID_FUNCTION (Win32 error 1) returned by FlushFileBuffers on a handle that does not support buffer flushing — typically anonymous pipes, NUL device, or files opened without the right flags. The CLI appears to call a sync/flush operation on stdout at exit and treats its failure as a fatal error, dropping the actual response from stdout and never writing the error to stderr unless stderr is captured independently.
This breaks every CI/automation/daemon scenario on Windows that uses subprocess.Popen (Python), Process.Start (.NET), child_process.spawn (Node), or any other launcher that creates pipe / regular-file stdout handles.
Environment
- Copilot CLI: 1.0.44-0 (
copilot --version) - OS: Windows 11
- Install: WinGet (
copilot.exeis a native binary, not an npm shim) - Auth:
copilot authshows a valid GitHub login
Reproduction
Working (PowerShell direct, file redirect)
copilot --prompt "respond with one word ok" --model claude-sonnet-4.5 --allow-all --no-ask-user > out.txt 2> err.txt
$LASTEXITCODE # 0 (success)Failing (Python subprocess, PIPE)
import subprocess
proc = subprocess.Popen(
["copilot", "--prompt", "respond with one word ok",
"--model", "claude-sonnet-4.5", "--allow-all", "--no-ask-user"],
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
out, err = proc.communicate(timeout=120)
print(proc.returncode) # 1
print(repr(out)) # ''
print(repr(err)) # ''Failing (Python subprocess, regular file)
import subprocess
out_f = open("out.txt", "wb")
err_f = open("err.txt", "wb")
proc = subprocess.Popen(
["copilot", "--prompt", "respond with one word ok",
"--model", "claude-sonnet-4.5", "--allow-all", "--no-ask-user"],
stdin=subprocess.DEVNULL, stdout=out_f, stderr=err_f,
)
proc.wait(timeout=120)
print(proc.returncode) # 1
print(open("out.txt","rb").read()) # b''
print(open("err.txt","rb").read()) # b'' (no message at all)Failing (cmd.exe with redirect)
proc = subprocess.Popen(
["cmd.exe", "/c",
'copilot --prompt "respond with one word ok" --model claude-sonnet-4.5 --allow-all --no-ask-user > out.txt 2> err.txt'],
stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True,
)
proc.communicate(timeout=120)
# Exit 1, no files created.Surfaces the actual error (Python subprocess, DEVNULL stdout + PIPE stderr)
proc = subprocess.Popen(
["copilot", "--prompt", "respond with one word ok",
"--model", "claude-sonnet-4.5", "--allow-all", "--no-ask-user"],
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.PIPE,
text=True,
)
out, err = proc.communicate(timeout=120)
print(proc.returncode) # 1
print(err)
# Error: Failed to sync '<stdout>': Incorrect function.Working (Python subprocess, wrapped in pwsh.exe -c "... > out 2> err")
proc = subprocess.Popen(
["pwsh.exe", "-NoProfile", "-NonInteractive", "-Command",
'copilot --prompt "respond with one word ok" --model "claude-sonnet-4.5" --allow-all --no-ask-user > out.txt 2> err.txt ; exit $LASTEXITCODE'],
stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True,
)
proc.communicate(timeout=180)
# Exit 0, out.txt has response, err.txt has the normal token-summary footer.This confirms the workaround and isolates the bug to how the CLI's runtime treats the stdout handle when it isn't the kind PowerShell's native > operator creates.
Expected behavior
- The CLI should not call
FlushFileBuffers(or equivalent) on stdout when the handle does not support it.GetFileType()on the handle would let it skip the flush forFILE_TYPE_PIPE,FILE_TYPE_CHAR, etc. - Failing that, a flush failure at exit should not be promoted to a fatal exit-1 — the actual response data has already been written.
- At minimum, the error message should be flushed to stderr (with a
flush()beforeexit()) so consumers can diagnose the failure. Today the message is lost in PIPE/PIPE mode because the panic path apparently aborts before stderr is flushed.
Actual behavior
- Exit code 1 with no output on either stream
- Buffered token-summary footer that normally goes to stderr is also lost
- Every CI/automation tool on Windows fails silently
Impact
This blocks all programmatic use of Copilot CLI from Windows automation:
- Daemons / background workers (e.g., PR-review bots that invoke
copilot) - CI pipelines that aren't wrapped in PowerShell
- IDE integrations that use
child_process.spawn/ equivalent - Any non-interactive scenario using Python, Node, .NET, Go, Rust, etc.
The current workaround (wrap every invocation in pwsh.exe -NoProfile -NonInteractive -Command "... > out 2> err") adds an extra process per call and is fragile (string-encoded args, encoding issues with the temp files, etc.).
Suggested fix
In the CLI's process-exit / stream-flush path, gate the explicit stdout sync on GetFileType(stdout) == FILE_TYPE_DISK, or wrap it in a try/catch that does not promote the failure to exit code 1 (since the data has already been written).
Independently, make sure stderr is flushed before exit so that any startup / runtime error is observable from automation.
Notes
- I previously filed -p / --prompt tokenizes value on whitespace, breaking all multi-word non-interactive prompts on v1.0.44-0 (Windows) #3186 which I will close — that one was based on a broken test harness (PowerShell
Start-Process -ArgumentListmangles argv around spaces) and incorrectly attributed the failure to-p/--prompttokenization. This issue is the corrected analysis with proof.
Activity
polajenko commentedon May 27, 2026
Ran into the same issue on v1.0.54 (Windows PowerShell). The response is completely absent from stdout in
-pmode — only the stats footer is written. Confirmed by capturing raw bytes.Additional findings:
-s/--silentflag is also broken — produces empty output entirely--screen-reader,--no-color,--no-custom-instructionsall have the same result2>&1,Out-File,Out-String) — not just subprocess launchersWorkaround that works:
--output-format jsonbypasses the TUI renderer entirely and writes JSONL directly to stdout.Closing #3544 as a duplicate of this issue.
patniko commentedon Oct 26, 2026
Thanks for the report. We've shipped fixes in this area since this was filed, and we believe this may now be resolved. Could you retest on the latest release (Copilot CLI v1.0.103) and let us know whether you still see it? If we don't hear back in a couple of weeks, we may close this issue — you can always reopen it.
Triaged as part of a Copilot SDK backlog review, with help from GitHub Copilot.