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

  1. Pass the real socket object or its integer fd, and verify it is open before use
  2. In tests, give mocks a fileno() returning a valid unique int, or use a real socketpair
  3. Check for closure (sock.fileno() >= 0) and re-establish the connection instead of reusing dead fds
  4. 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

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


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