python/cpython · error · Error

Failed to fetch glossary.json

Error message

Failed to fetch glossary.json

What it means

Raised by _ProactorBaseWritePipeTransport.write() on Windows IOCP event loops when write() is called after write_eof() has already been invoked on the same transport. write_eof() signals that no more data will be written and half-closes the pipe/socket, so any subsequent write is a protocol violation. It almost always indicates a race where one part of the code finished the stream while another still tried to send data.

Source

Thrown at Doc/tools/static/glossary_search.js:8

"use strict";

const GLOSSARY_PAGE = "glossary.html";

const glossary_search = async () => {
  const response = await fetch("_static/glossary.json");
  if (!response.ok) {
    throw new Error("Failed to fetch glossary.json");
  }
  const glossary = await response.json();

  const params = new URLSearchParams(document.location.search).get("q");
  if (!params) {
    return;
  }

  const searchParam = params.toLowerCase();
  const glossaryItem = glossary[searchParam];
  if (!glossaryItem) {
    return;
  }

  // set up the title text with a link to the glossary page
  const glossaryTitle = document.getElementById("glossary-title");
  glossaryTitle.textContent = "Glossary: " + glossaryItem.title;
  const linkTarget = searchParam.replace(/ /g, "-");

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Audit call sites: ensure no task writes to the transport after write_eof() is called; guard writes with an 'eof_sent' flag shared across tasks
  2. Synchronize the writer and the closer with an asyncio.Event or by awaiting drain()/writer completion before write_eof()
  3. For subprocess stdin, use wait_closed() (Python 3.7+/3.12 fixes) after write_eof() and cancel/await the writer task before closing
  4. Catch RuntimeError around the offending write if it is a benign teardown race and log/ignore it deliberately

Example fix

// before
async def talk(proc):
    proc.stdin.write(b'data')
    proc.stdin.write_eof()
    proc.stdin.write(b'more')  # RuntimeError
// after
async def talk(proc):
    proc.stdin.write(b'data')
    await proc.stdin.drain()
    proc.stdin.write_eof()
    await proc.stdin.wait_closed()
Defensive patterns

Strategy: validation

Validate before calling

async def safe_write(tr, data, state):
    if state['eof']:
        raise RuntimeError('refusing to write after write_eof')
    tr.write(data)
    await tr.drain()

async def close_writer(tr, state):
    state['eof'] = True
    tr.write_eof()
    await tr.wait_closed()

Try / catch

try:
    tr.write(data)
except RuntimeError as e:
    if 'write_eof() already called' in str(e):
        logger.warning('write after EOF during teardown: %r', e)
    else:
        raise

Prevention

When it happens

Trigger: Calling transport.write(data) after transport.write_eof() on a proactor-based transport (Windows ProactorEventLoop, subprocess stdin pipes, pipe transports). Typical with asyncio subprocess wrappers where stdin.write() races with stdin.write_eof()/close, or a protocol's connection_lost cleanup overlaps with a pending write.

Common situations: Windows-only asyncio applications using subprocess stdin pipes (a writer task and a closer task not synchronized); HTTP/client code that closes a request body then retries a send; porting selector-loop code to Windows where the proactor loop enforces this check eagerly; mixing transport.close() with buffered writes still in flight from another task.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/b05e83563b83bc05. Report an issue: GitHub.