python/cpython · error · ExtensionError
profiling_trace: Placeholder pattern not found in {js_path.n
Error message
profiling_trace: Placeholder pattern not found in {js_path.name} What it means
_ensure_fd_no_transport() raises ValueError('Invalid file object: ...') when asked for a file descriptor and the object is neither an int nor something with a working fileno(). This mirrors selectors._fileobj_tofd: the fd must be an integer or expose .fileno() returning one. It is a caller-contract error at the point a socket/fd is registered with the loop.
Source
Thrown at Doc/tools/extensions/profiling_trace.py:152
trace = generate_trace(DEMO_SOURCE)
demo_data = {'source': DEMO_SOURCE.rstrip(), 'trace': trace, 'samples': []}
demo_json = json.dumps(demo_data, indent=2)
content = js_path.read_text(encoding='utf-8')
pattern = r"(const DEMO_SIMPLE\s*=\s*/\* PROFILING_TRACE_DATA \*/)[^;]+;"
if re.search(pattern, content):
content = re.sub(
pattern, lambda m: f"{m.group(1)} {demo_json};", content
)
js_path.write_text(content, encoding='utf-8')
print(
f"profiling_trace: Injected {len(trace)} trace events into {js_path.name}"
)
else:
raise ExtensionError(
f"profiling_trace: Placeholder pattern not found in {js_path.name}"
)
def add_assets(app, pagename, templatename, context, doctree):
if pagename == 'library/profiling.sampling':
app.add_js_file('profiling-sampling-visualization.js')
app.add_css_file('profiling-sampling-visualization.css')
def setup(app):
app.connect('build-finished', inject_trace)
app.connect('html-page-context', add_assets)
return {
'version': '1.0',
'parallel_read_safe': True,
'parallel_write_safe': True,View on GitHub (pinned to bc6749cc3b)
Solutions
- Pass the real socket object or its integer fd, and verify it is open before use
- In tests, give mocks a fileno() returning a valid unique int, or use a real socketpair
- Check for closure (sock.fileno() >= 0) and re-establish the connection instead of reusing dead fds
- Fix call sites after refactors so the socket itself, not a wrapper, is handed to loop APIs
Example fix
# before loop.add_reader(fake_obj, cb) # fake_obj has no fileno -> ValueError # after r, _ = socket.socketpair() loop.add_reader(r, cb, r)
Defensive patterns
Strategy: validation
Validate before calling
def fd_of(obj):
if isinstance(obj, int):
return obj
try:
fd = int(obj.fileno())
except (AttributeError, TypeError, ValueError):
raise ValueError(f'Invalid file object: {obj!r}') from None
if fd < 0:
raise ValueError(f'file object is closed: {obj!r}')
return fd Type guard
def has_valid_fileno(obj) -> bool:
try:
return int(obj.fileno()) >= 0
except (AttributeError, TypeError, ValueError):
return False Try / catch
try:
loop.add_reader(sock, cb)
except ValueError as e:
if 'Invalid file object' in str(e):
raise TypeError(f'pass an open socket, got {sock!r}') from e
raise Prevention
- Hand the socket object itself (or its int fd) to loop APIs
- Verify fileno() >= 0 before registering; recreate closed connections
- Give test mocks a fileno() returning unique positive ints
- Update call sites when refactors replace sockets with wrapper objects
When it happens
Trigger: Passing an already-closed socket whose fileno() returns -1 or raises, a mock/dummy object in tests whose fileno() raises ValueError, a plain object (str, dict) where a socket was expected, or an fd wrapper that raises TypeError in __int__-like conversion. Hit via loop.add_reader/add_writer, sock_* APIs, or transport creation that route through _ensure_fd_no_transport.
Common situations: Unit tests with unittest.mock sockets lacking a real fileno(); using closed sockets after close() (fileno() == -1 path differs but similar mocks fail here); passing an SSL object or file wrapper whose fileno is unavailable; refactor changing a parameter from socket to a handler object while call sites were not updated.
Related errors
- Unimplemented ioctl request
- deprecated-removed:: second argument cannot be `next`
- BUILD_GNU_TYPE is not defined
- offset must be a non-negative integer (got {!r})
- server_hostname is only meaningful with ssl
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/8437c2df5d335794.
Report an issue: GitHub.