Skip to content

wsl --list / wsl --status write nothing to stdout when it is redirected or piped (exit code 0) #41937

Closed

Description

@JiuJiuYeha

Environment

  • Windows 11 build 10.0.26200.9457
  • WSL 3.0.3.0 (MSI install at C:\Program Files\WSL, installed 2026-10-14)
  • Kernel 6.18.54.1-1, WSLg 1.0.79
  • WSLService running normally
  • Two registered distributions: Debian (default) and Ubuntu, both WSL2
    • HKCU\Software\Microsoft\Windows\CurrentVersion\Lxss keys complete (11 values each, State=1, Flags=15)
    • AppX packages Status = Ok
    • wsl -d Debian -e ..., wsl -d Ubuntu -e ..., wsl --system -e ... all work correctly

Steps to reproduce

  1. Open cmd.exe in a console window.

  2. Run:

    wsl -l -v
    

    Result: the table prints correctly:

      NAME      STATE           VERSION
    * Debian    Running         2
      Ubuntu    Running         2
    

    wsl --status likewise prints 默认发行版: Debian / 默认版本: 2 correctly.

  3. Run the same command with stdout redirected:

    wsl -l -v > out.txt
    echo %ERRORLEVEL%
    

    Result: out.txt is 0 bytes, %ERRORLEVEL% is 0.

  4. Run it through a pipe:

    wsl -l -q | findstr .
    

    Result: downstream receives nothing.

Expected behavior

stdout should contain the same content regardless of whether stdout is a console, a pipe, or a file (as it did in WSL 2.x, where wsl -l -q produced UTF-16 output).

Actual behavior

Output is only emitted when stdout is a console handle. When stdout is redirected or piped, the command writes nothing at all — no error, no partial output — and still exits with code 0, so callers cannot distinguish "no distributions installed" from "the command is broken".

Also affected

  • wsl --status
  • wsl --list --online
  • wsl --list --running, wsl --list --quiet (all variants)
  • wslc container list (same CLI table-output layer)
  • inbox C:\Windows\System32\wslconfig.exe /list → also 0 bytes, exit 0

Not affected

wsl --version, wsl --help, and error messages from the same binary are written to a redirected stdout correctly (e.g. wsl --version > f.txt yields 362 bytes). So the problem is specific to the table/status output path.

Things already ruled out (all still reproduce)

  • Removing %USERPROFILE%\.wslconfig entirely
  • WSL_UTF8=1 / WSL_DISABLE_WARNINGS=1
  • Invoking C:\Windows\System32\wsl.exe vs "C:\Program Files\WSL\wsl.exe"
  • Running with no console attached vs. inside a real console window (spawned via Start-Process): same result
  • Registry / AppX state: both Lxss keys and AppX packages are intact
  • Service state: WSLService running, binary versions consistent with the install directory

Impact

Any tool that enumerates distributions by capturing wsl.exe stdout is affected.

Concrete case: VS Code Remote-WSL (ms-vscode-remote.remote-wsl 0.104.3) calls

const e = await this.wslExecServer.runWSLCommandLine(["--list", "--verbose"]);
if (!e.status) return this.parseDistros(e.stdout, ...);   // exit code is 0

It gets an empty string, parses 0 distributions, logs No distros found, then its wslconfig /list fallback also returns nothing, and resolveAuthority(wsl) hangs until it is canceled (observed: 141 s / 218 s / 6 s before Canceled). From the user's perspective VS Code simply "cannot detect any WSL distribution".

Suspected cause

Regression in the 3.0.x CLI table-output rework (CLI: Table output with color and routing support, #40848): the table/status writer appears to take a console-only path (WriteConsoleW) and silently skips writing when stdout is not a console.

Activity

  1. github-actions commented on Oct 15, 2026

    @github-actions
    Contributor

    Logs are required for review from WSL team

    If this a feature request, please reply with '/feature'. If this is a question, reply with '/question'.
    Otherwise, please attach logs by following the instructions below, your issue will not be reviewed unless they are added. These logs will help us understand what is going on in your machine.

    How to collect WSL logs

    Download and execute collect-wsl-logs.ps1 in an administrative powershell prompt:

    Invoke-WebRequest -UseBasicParsing "https://raw.githubusercontent.com/microsoft/WSL/master/diagnostics/collect-wsl-logs.ps1" -OutFile collect-wsl-logs.ps1
    Set-ExecutionPolicy Bypass -Scope Process -Force
    .\collect-wsl-logs.ps1
    

    The script will output the path of the log file once done.

    If this is a networking issue, please use .\collect-wsl-logs.ps1 -LogProfile networking instead, following the instructions in Collect WSL logs for networking issues

    Once completed please upload the output files to this GitHub issue.

    See Collect WSL logs (recommended method).

    If you choose to email these logs instead of attaching them to the bug, please send them to [email protected] with the GitHub issue number in the subject, and include a link to your GitHub issue comment in the message body, and reply with '/emailed-logs'.

  2. JiuJiuYeha commented on Oct 16, 2026

    @JiuJiuYeha
    Author

    wsl41937-repro-evidence.zip

    Logs collected — plus two new findings: the bug is nondeterministic, and successful output is UTF-16LE

    I collected logs with the official collect-wsl-logs.ps1 (default WPR profile) while reproducing. The full ETW trace (logs.etl, 1.15 GB raw) exceeds the GitHub attachment limit — happy to provide it on request (upload or email to [email protected]).

    New finding 1: the empty output is nondeterministic (~30/70).

    Yesterday the repro was 100% deterministic (always 0 bytes). Today, while the WPR trace was running, the same command sometimes succeeds:

    cmd.exe /c "wsl.exe --list --verbose > out.txt 2>&1"

    runs with output empty
    12 consecutive 3 9
    10 consecutive ~220ms apart 2 8
    6 with 2s delay 2 4
    8 with WSL_UTF8=1 4 4

    Exit code is 0 in all 44 runs. Console code page (65001 / 936 / 437) showed no correlation. This suggests a race in the redirected-output path rather than a missing code path.

    New finding 2: when output IS produced, it is UTF-16LE — even with WSL_UTF8=1.

    Successful capture (loop_2.txt in the zip) hex-dumps as 20 00 20 00 4E 00 … and decodes to the correct table. So a consumer that redirects stdout gets UTF-16LE (nondeterministically) or nothing at all; WSL_UTF8=1 has no effect on this path.

    wsl --status appears to be a separate, deterministic bug: redirected output was 0 bytes in all runs — no nondeterminism observed.

    Attached: wsl41937-repro-evidence.zip — all 44 repro output files (the empty ones are evidence too) + RESULTS-SUMMARY.txt + README.txt + collection info.

    Environment: WSL 3.0.3.0 (MSI install), Windows 11 10.0.26200.9457, two healthy WSL2 distros (Debian default + Ubuntu).

  3. github-actions commented on Oct 16, 2026

    @github-actions
    Contributor

    No logs.etl found in the archive. Make sure that you ran collect-wsl-logs.ps1 as administrator and that the logs.etl file is in the archive.

    Diagnostic information
    appxpackage.txt not found
    optional-components.txt not found
    No logs.etl found in archive.
    Error while parsing the logs. See action page for details
    
  4. JiuJiuYeha commented on Oct 16, 2026

    @JiuJiuYeha
    Author

    WslLogs-2026-10-16_10-48-44.tar.gz

    Full logs attached — collect-wsl-logs.ps1 output, logs.etl from a 15s WPR (WSL profile) capture with wpr -start/-stop both exiting 0.

    Repro runs were executed inside the capture window, so the ETW trace contains the failing wsl.exe --list --verbose invocations.

    Two corrections/additions to my previous comment:

    1. The bug is nondeterministic, not deterministic. Across 91 redirected runs in 4 rounds: wsl --list --verbose produced output in ~40% of runs (11/44, 7/20, 8/15, 7/12), wsl --status in 2/7. Exit code is 0 in every single run. This looks like a race in the redirected-output path — worth checking whether the writer can exit before the console/output buffer is flushed when stdout is not a console.

    2. Correction to my previous comment: I wrote that wsl --status "appears to be a separate, deterministic bug" — that was based on a small sample. It is also nondeterministic (2/7 non-empty).

    Also confirmed again: whenever output does appear it is UTF-16LE, even with WSL_UTF8=1 (e.g. repro/r2_status_2.txt starts d8 9e = U+9ED8). Console code page (65001/936/437) has no effect.

    Archive contents: logs.etl (44 MB), wpr.txt (start/stop codes), all repro captures from the 4 rounds in repro/ (empty files are evidence too) with FINAL-SUMMARY.txt, plus the standard environment files.

  5. github-actions commented on Oct 16, 2026

    @github-actions
    Contributor
    Diagnostic information
    .wslconfig found
    Detected appx version: 3.0.3.0
    Unexpected format in optional-component.txt: State       : EnablePending
    
  6. chemwolf6922 commented on Oct 16, 2026

    @chemwolf6922
    Contributor

    Hi JiuJiuYeha .
    Please attach a short Procmon PML covering one empty-output run and one successful wsl --list --verbose run. Capture File System and Process/Thread activity and save all events.
    Please check that the log does not contain sensitive data before sharing.

  7. JiuJiuYeha commented on Oct 16, 2026

    @JiuJiuYeha
    Author

    Hi Feng Wang, thanks for looking into this.

    Background / how I got here: after upgrading to WSL 3.0, opening VS Code
    could no longer connect into my WSL environment - it failed with a "distro not
    found" style error. While debugging that I noticed wsl --list / wsl --status
    sometimes print nothing when stdout is redirected or piped (exit code still 0),
    which is what this issue is about.

    Procmon capture attached (wsl41937-procmon.tgz, 14 MB) as requested:

    • One empty-output run and several successful runs of
      wsl --list --verbose are all covered.

    • Captured with Procmon64 using /BackingFile, no filters applied, and
      all events saved - File System and Process/Thread activity included
      (Profiling disabled).

    • Repro command: cmd.exe /c "wsl.exe --list --verbose > run_N.txt 2>&1",
      every run exiting with code 0.

    • Exact timestamps of each run (UTC+8), from runs-log.txt inside the archive:

      run start -> end stdout
      1 15:11:49.828 -> 15:11:50.380 198 bytes (UTF-16LE)
      2 15:11:50.495 -> 15:11:50.895 198 bytes (UTF-16LE)
      3 15:11:50.901 -> 15:11:51.370 198 bytes (UTF-16LE)
      4 15:11:51.375 -> 15:11:51.836 198 bytes (UTF-16LE)
      5 15:11:51.843 -> 15:11:52.302 0 bytes (EMPTY)
    • Sensitive-data check: before sharing, I scanned the capture for
      credentials (JWTs, token=/secret=/password=, bearer/authorization
      headers, private keys, AWS/GitHub key patterns) in both ASCII and UTF-16 -
      zero matches. Processes that put tokens on their command lines (WeCom, VS
      Code remote sessions) were closed during the capture window.

    Extracting: the archive is gzip'ed tar containing an xz-compressed PML
    (GitHub's 25 MB limit):

    tar -xzf wsl41937-procmon.tgz && xz -d capture.pml.xz
    # then open capture.pml in Procmon, or:
    Procmon64.exe /OpenLog capture.pml
    7-Zip can also extract both layers directly. README-PROCmon.txt in the
    archive repeats these instructions.
    
    [wsl41937-procmon.tgz](https://github.com/user-attachments/files/33531870/wsl41937-procmon.tgz)
  8. JiuJiuYeha commented on Oct 16, 2026

    @JiuJiuYeha
    Author
  9. chemwolf6922 commented on Oct 22, 2026

    @chemwolf6922
    Contributor

    Hi JiuJiuYeha .
    Thanks for the capture. The data shows that some iOA (Tencent security software) logic (likely a bug) causes the process to terminate early during process shutdown. Which causes the output to be not flushed sometimes. The dll is Txumon64.dll. Please consider reporting this to your IT or Tencent to investigate this failure.

  10. chemwolf6922 commented on Oct 22, 2026

    @chemwolf6922
    Contributor

    Closing this as the cause is external.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

externalIssue exists outside of WSL componentswsl2Issue/feature applies to WSL 2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions