Skip to content

oikb validate --deep crashes with cryptic TypeError: ('parser', <class 'module'>) on Windows #92

Description

@Nemo08

Title

oikb validate --deep crashes with cryptic TypeError: ('parser', <class 'module'>) on Windows — actual cause is stale trio incompatible with Python 3.13's pathlib.Path.parser

Summary

On Windows, oikb validate --deep (and in fact any oikb command that constructs an httpx.Client) can fail with a confusing, non-actionable error:

Deep validation
  ✗ Cannot reach Open WebUI: ('parser', <class 'module'>)

This looks like a network/connectivity problem, but it isn't — httpx.Client() never even gets to make a request. The root cause is an environment issue (outdated trio), but oikb's error handling in cli.py swallows the real traceback and prints only str(e), which for multi-arg exceptions is just repr(e.args). This makes the message actively misleading for anyone trying to diagnose a "connectivity" failure that has nothing to do with the network.

Environment

  • OS: Windows (PowerShell)
  • Python: 3.13.x
  • oikb: 0.4.0
  • httpx: 0.28.1
  • httpcore: 1.0.9
  • trio: 0.23.1 (before fix) — pulled in transitively via selenium / trio-websocket, used by httpcore._synchronization for sync primitives

Root cause

httpcore._synchronization imports trio on Windows for its locking primitives. trio's _path.py defines trio.Path by wrapping every method of pathlib.Path/PurePath via a metaclass (AsyncAutoWrapperType.generate_forwards), iterating over pathlib.Path's class attributes.

Python 3.13 added a new class attribute to pathlib.PurePath: parser (a module reference, e.g. posixpath/ntpath, part of the new path-flavour abstraction). Older versions of trio (e.g. 0.23.1) assume every wrapped attribute is callable/descriptor-like and blow up when it encounters a bare module:

# trio/_path.py, generate_forwards()
raise TypeError(attr_name, type(attr))
# -> TypeError('parser', <class 'module'>)

This exception propagates all the way up through httpcorehttpx.Client.__init__oikb._make_client(), where cli.py catches it as a generic Exception and prints:

except Exception as e:
    click.echo(click.style(f"  ✗ Cannot reach Open WebUI: {e}", fg="red"))

Since the TypeError was raised with two positional args, str(e) renders as repr(e.args) — hence the odd ('parser', <class 'module'>) output, with zero indication that this is an import-time failure unrelated to networking.

Fix on the user side: pip install --upgrade trio (0.23.1 → 0.33.0 resolves it).

Reproduction

python -c "import httpx; httpx.Client()"

On an affected environment (Python 3.13 + trio < ~0.26) this raises the traceback below instead of returning silently.

Full traceback
Traceback (most recent call last):
  File "<string>", line 1, in <module>
    import httpx; httpx.Client()
  File "...\httpx\_client.py", line 688, in __init__
    self._transport = self._init_transport(...)
  File "...\httpx\_client.py", line 731, in _init_transport
    return HTTPTransport(...)
  File "...\httpx\_transports\default.py", line 150, in __init__
    import httpcore
  File "...\httpcore\__init__.py", line 1, in <module>
    from ._api import request, stream
  File "...\httpcore\_api.py", line 7, in <module>
    from ._sync.connection_pool import ConnectionPool
  File "...\httpcore\_sync\__init__.py", line 1, in <module>
    from .connection import HTTPConnection
  File "...\httpcore\_sync\connection.py", line 14, in <module>
    from .._synchronization import Lock
  File "...\httpcore\_synchronization.py", line 12, in <module>
    import trio
  File "...\trio\__init__.py", line 77, in <module>
    from ._path import Path as Path
  File "...\trio\_path.py", line 201, in <module>
    class Path(metaclass=AsyncAutoWrapperType):
  File "...\trio\_path.py", line 145, in __init__
    type(cls).generate_forwards(cls, attrs)
  File "...\trio\_path.py", line 162, in generate_forwards
    raise TypeError(attr_name, type(attr))
TypeError: ('parser', <class 'module'>)

Suggested fixes for oikb

None of this is oikb's bug per se (it's an upstream trio/Python 3.13 incompatibility), but oikb's error handling makes it very hard to diagnose. Suggestions, roughly in order of preference:

  1. In _make_client() / the validate --deep handler, catch import/construction errors from httpx.Client() separately and print the full exception type + traceback (or at least repr(e) instead of str(e)) so users can see it's a TypeError on import, not a connection failure.
  2. Consider whether httpcore's optional trio backend needs to be pulled in at all for oikb's use case (oikb only uses the sync httpx.Client, not httpx.AsyncClient) — if there's a way to avoid triggering the trio import path for sync-only usage, that would sidestep this class of issue entirely.
  3. Document a minimum trio version (or add trio>=0.26 as an explicit constraint) in pyproject.toml if httpcore/trio end up in the dependency tree on Windows, since older trio is incompatible with Python 3.13.
  4. At minimum, mention this failure mode in the troubleshooting docs — "Cannot reach Open WebUI: ('parser', <class 'module'>)" is a decent search-engine anchor for future users hitting the same thing.

Additional notes

Direct connectivity to Open WebUI was confirmed working the whole time (curl -i $OPEN_WEBUI_URL/health returned 200 OK) while oikb validate --deep reported "Cannot reach Open WebUI" — worth flagging explicitly in any fix/doc update that this message can be a false negative for network reachability.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions