{"record":{"id":"b05e83563b83bc05","repo":"python/cpython","slug":"failed-to-fetch-glossary-json","errorCode":null,"errorMessage":"Failed to fetch glossary.json","messagePattern":"Failed to fetch glossary\\.json","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"Doc/tools/static/glossary_search.js","lineNumber":8,"sourceCode":"\"use strict\";\n\nconst GLOSSARY_PAGE = \"glossary.html\";\n\nconst glossary_search = async () => {\n  const response = await fetch(\"_static/glossary.json\");\n  if (!response.ok) {\n    throw new Error(\"Failed to fetch glossary.json\");\n  }\n  const glossary = await response.json();\n\n  const params = new URLSearchParams(document.location.search).get(\"q\");\n  if (!params) {\n    return;\n  }\n\n  const searchParam = params.toLowerCase();\n  const glossaryItem = glossary[searchParam];\n  if (!glossaryItem) {\n    return;\n  }\n\n  // set up the title text with a link to the glossary page\n  const glossaryTitle = document.getElementById(\"glossary-title\");\n  glossaryTitle.textContent = \"Glossary: \" + glossaryItem.title;\n  const linkTarget = searchParam.replace(/ /g, \"-\");","sourceCodeStart":1,"sourceCodeEnd":26,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Doc/tools/static/glossary_search.js#L1-L26","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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","Synchronize the writer and the closer with an asyncio.Event or by awaiting drain()/writer completion before write_eof()","For subprocess stdin, use wait_closed() (Python 3.7+/3.12 fixes) after write_eof() and cancel/await the writer task before closing","Catch RuntimeError around the offending write if it is a benign teardown race and log/ignore it deliberately"],"exampleFix":"// before\nasync def talk(proc):\n    proc.stdin.write(b'data')\n    proc.stdin.write_eof()\n    proc.stdin.write(b'more')  # RuntimeError\n// after\nasync def talk(proc):\n    proc.stdin.write(b'data')\n    await proc.stdin.drain()\n    proc.stdin.write_eof()\n    await proc.stdin.wait_closed()","handlingStrategy":"validation","validationCode":"async def safe_write(tr, data, state):\n    if state['eof']:\n        raise RuntimeError('refusing to write after write_eof')\n    tr.write(data)\n    await tr.drain()\n\nasync def close_writer(tr, state):\n    state['eof'] = True\n    tr.write_eof()\n    await tr.wait_closed()","typeGuard":null,"tryCatchPattern":"try:\n    tr.write(data)\nexcept RuntimeError as e:\n    if 'write_eof() already called' in str(e):\n        logger.warning('write after EOF during teardown: %r', e)\n    else:\n        raise","preventionTips":["Track EOF state in one place shared by all writers of a transport","Await drain() and wait_closed() before/after write_eof so writes finish first","Cancel and await writer tasks before closing a subprocess stdin","Never call write_eof() from multiple tasks"],"tags":["asyncio","windows","transport","race-condition","subprocess"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}