claude-code - 💡(How to fix) Fix skill-creator run_eval.py: Windows incompatibility — select.select() fails on pipe handles (WinError 10038)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Fix Action

Fix

Replace select.select() + os.read() with a background reader thread using queue.Queue. This is cross-platform and works on Windows pipe handles:

import queue as queue_module
import threading

def _reader_thread(stdout, q):
    try:
        for line in iter(stdout.readline, b''):
            q.put(line)
    finally:
        q.put(None)

# In run_single_query, replace the select loop with:
output_queue = queue_module.Queue()
reader = threading.Thread(target=_reader_thread, args=(process.stdout, output_queue), daemon=True)
reader.start()

while time.time() - start_time < timeout:
    try:
        chunk = output_queue.get(timeout=0.5)
    except queue_module.Empty:
        if process.poll() is not None:
            break
        continue
    if chunk is None:
        break
    line = chunk.decode("utf-8", errors="replace").strip()
    # ... rest of event parsing ...

Code Example

python -m scripts.run_loop --eval-set <any-eval-set.json> --skill-path <any-skill> --model claude-sonnet-4-6 --max-iterations 1 --verbose --report none

---

import queue as queue_module
import threading

def _reader_thread(stdout, q):
    try:
        for line in iter(stdout.readline, b''):
            q.put(line)
    finally:
        q.put(None)

# In run_single_query, replace the select loop with:
output_queue = queue_module.Queue()
reader = threading.Thread(target=_reader_thread, args=(process.stdout, output_queue), daemon=True)
reader.start()

while time.time() - start_time < timeout:
    try:
        chunk = output_queue.get(timeout=0.5)
    except queue_module.Empty:
        if process.poll() is not None:
            break
        continue
    if chunk is None:
        break
    line = chunk.decode("utf-8", errors="replace").strip()
    # ... rest of event parsing ...
RAW_BUFFERClick to expand / collapse

Bug

scripts/run_eval.py uses select.select([process.stdout], [], [], 1.0) to check subprocess stdout readiness. On Windows, select.select() only supports sockets (Winsock), not pipe file handles. This raises [WinError 10038] on every query, causing all trigger evaluations to silently fall back to False (recall = 0% across the entire eval set).

Impact

The description optimization loop (run_loop.py) is completely non-functional on Windows — every iteration reports 0% recall regardless of description quality, making the tool useless for Windows users.

Reproduction

Run on Windows:

python -m scripts.run_loop --eval-set <any-eval-set.json> --skill-path <any-skill> --model claude-sonnet-4-6 --max-iterations 1 --verbose --report none

Expected: eval queries return meaningful trigger rates. Actual: [WinError 10038] on every query, all trigger rates = 0/3.

Fix

Replace select.select() + os.read() with a background reader thread using queue.Queue. This is cross-platform and works on Windows pipe handles:

import queue as queue_module
import threading

def _reader_thread(stdout, q):
    try:
        for line in iter(stdout.readline, b''):
            q.put(line)
    finally:
        q.put(None)

# In run_single_query, replace the select loop with:
output_queue = queue_module.Queue()
reader = threading.Thread(target=_reader_thread, args=(process.stdout, output_queue), daemon=True)
reader.start()

while time.time() - start_time < timeout:
    try:
        chunk = output_queue.get(timeout=0.5)
    except queue_module.Empty:
        if process.poll() is not None:
            break
        continue
    if chunk is None:
        break
    line = chunk.decode("utf-8", errors="replace").strip()
    # ... rest of event parsing ...

Environment

  • Windows 11 Enterprise 10.0.26200
  • Python 3.x (PowerShell)
  • Claude Code CLI, skill-creator plugin

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING