You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Revisit single-use semantics of StreamableHTTPSessionManager.run() #1692
StreamableHTTPSessionManager currently enforces that run() can only be called once per instance. This is documented but not explained, and it complicates:
testing (each test must construct a new manager), and
any scenario that might want to reuse the manager for restarts.
It would be useful to either:
make run() safely reusable, or
codify and enforce single-use semantics in a clearer way.
Problems
Testing: Requiring a new manager instance for each run increases boilerplate and can hide lifecycle issues.
Unclear constraints: Users have to discover via runtime errors that run() is single-use, without an obvious reason.
Lifecycle complexity: The single-use constraint is a hint that some internal state (task groups, resource stacks) is not being fully reset.
Proposal
Investigate why single-use is required
Document what internal state is left behind after run() completes (e.g., background tasks, queues).
Determine whether these can be safely reset at the start of the next run().
Either: make run() reusable...
Reset internal state (task groups, lists of tasks, queues) before each run().
Ensure proper cleanup in finally blocks so the manager returns to a clean state.
...or explicitly codify single-use semantics
If reuse is fundamentally unsafe, consider:
modelling the manager as a consumable object (e.g., via documentation and type hints),
or returning a token/handle that marks the manager as “exhausted” after run().
Why this matters
Developer experience: Easier to write tests that exercise multiple lifecycles.
Robustness: Cleaning up state between runs reduces the risk of hidden leaks or race conditions.
Clarity: Either outcome (reusable or explicitly consumable) is better than a hidden constraint.
Acceptance criteria
The rationale for single-use semantics is documented (if they remain).
Either:
run() can be safely called multiple times on the same instance, or
Single-use semantics are enforced and clearly documented.
Tests cover repeated calls to run() and confirm expected behavior.
Pinging to check if there's any appetite for resolving this. I'm happy to open a PR.
Looking at the current implementation in streamable_http_manager.py, run() sets self._has_started = True and never resets it, so any subsequent call unconditionally raises a RuntimeError. The fix would be relatively small in either direction.
Before investing the effort I'd like alignment on the preferred approach:
Make run() reusable — reinitialize state (_server_instances, _task_group) at the start of each run() call and ensure the finally block leaves things in a clean state. This would be a small change and would directly improve testability.
Explicitly codify single-use — if reuse is fundamentally unsafe (e.g. due to anyio Lock objects not being safely recreatable after a task group is cancelled), keep the guard but raise a more descriptive error and document the rationale clearly.
Is there a preferred direction? Or is there a technical reason why reuse is intentionally unsafe that I may have missed?
Activity
dgenio commentedon Apr 9, 2026
Pinging to check if there's any appetite for resolving this. I'm happy to open a PR.
Looking at the current implementation in
streamable_http_manager.py,run()setsself._has_started = Trueand never resets it, so any subsequent call unconditionally raises aRuntimeError. The fix would be relatively small in either direction.Before investing the effort I'd like alignment on the preferred approach:
run()reusable — reinitialize state (_server_instances,_task_group) at the start of eachrun()call and ensure thefinallyblock leaves things in a clean state. This would be a small change and would directly improve testability.Lockobjects not being safely recreatable after a task group is cancelled), keep the guard but raise a more descriptive error and document the rationale clearly.Is there a preferred direction? Or is there a technical reason why reuse is intentionally unsafe that I may have missed?
maxisbey commentedon Aug 10, 2026
Thanks for the report. Closing this as part of a wider backlog cleanup following the v2 launch. If it's still relevant, feel free to reopen.